Silex, desarrollo web ágil y profesional con PHP

Post on 15-Jan-2015

13.327 views 4 download

description

Silex es el microframework de moda en el mundo PHP. Silex te permite desarrollar aplicaciones web profesionales con una agilidad sin precedentes. Su aprendizaje es tan rápido y sencillo que podrás dominarlo en menos de una hora.

Transcript of Silex, desarrollo web ágil y profesional con PHP

JAVIER EGUILUZBILBOSTACK26 ENERO 2013

Silexdesarrollo web ágil y profesional con PHP

Gracias a la organización.

Asier Fran Ibon Vicenç

Agenda1. Introducción

2. Programando aplicaciones

3. DEMO

4. Buenas prácticas

5. Puntos débiles

Introducción

¿Por qué?

En el mundo de los negocios...

1.Rápido

2.Barato

3.Bueno

En el mundo de los negocios...

1.Rápido

2.Barato

3.Bueno

ELIGE DOS

En el mundo de la programación...

1.Bien hecho

2.Terminado a tiempo

3.Barato

En el mundo de la programación...

1.Bien hecho

2.Terminado a tiempo

3.Barato

ELIGE UNA

En el mundo de la programación...

1.Bien hecho

2.Terminado a tiempo

3.Barato✔

Con Silex puedes tenerlo todo

¡quiero hacerlo bien!¡no tengo

tiempo!

¿Qué esSilex?

Foto: Wikipedia

Foto: WikipediaSojourner (2007)

Curiosity (2012)

Sojourner (2007)

Curiosity(2012)

Masa 11 kg 900 kg

Coste ($) 150 M 1.800 M

Memoria RAM 64 KB 256 MB

CPU 2 MHz 200 MHz

Es importante tener en cuenta que...

• El grande jamás podrá ser tan ágil como el pequeño.

• El pequeño jamás podrá competir en potencia y funcionalidad con el grande.

SilexThe PHP micro-frameworkbased on the Symfony2 Components

el logo de Silex

los dos son frameworks y usan los mismos componentes, pero...

...Symfony es un framework muy grande y Silex es un framework muy pequeño

Silex Symfony2

Peso 5 MB 8 MB

Archivos 3.366 6.578

Nivel dificultad

Flexibilidad

Los creadores de Silex

Fabien Potencier@fabpot

Igor Wiedler@igorw

+ fácil- calidad

+ calidad- facil

+ fácil- calidad

+ calidad- facil

Programandoaplicaciones

Funciones anónimasy closures

function suma($a, $b) { return $a + $b;}

Función normal

function ($a, $b) { return $a + $b;}

Función anónima

$app->get('...', function ($a, $b) { return $a + $b;});

Usando una función anónima

$a = 3;function ($b) { return $a + $b;}

Closure

$a = 3;function ($b) { return $a + $b;}

Closure

NO FUNCIONA

$a = 3;function ($b) use ($a) { return $a + $b;}

Closure

$app->get('...', function ($var) use ($app) { // ...});

El código más común de Silex

El primerejemplo

Holamundo.

http://bilbostack.com/hola

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Hola Mundo en Silex

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Cargar clases automáticamente

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Crear la aplicación Silex

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Ejecutar código para una URL

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Arrancar la aplicación

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hola', function() { return 'Hola mundo';});

$app->run();

Hola Mundo en Silex

require 'sinatra'

get '/hola' do "Hola mundo."end

Sinatra / Ruby

var http = require('http');

http.createServer(function (request, response) { response.writeHead( 200, { 'Content-Type': 'text/plain' } ); response.end('Hola mundo\n');}).listen(80);

node.js / JavaScript

Un ejemploreal

github.com/

javiereguiluz/bilbostack

Fork me on GitHub

Enrutamiento

$app->get('/', function () use ($app) { // ...});

Ruta de la portada

$app->get('/agenda', function () use ($app) { // ...});

Ruta básica

$app->get('/speakers/{slug}', function () use ($app) { // ...});

Ruta con partes variables

$app->get('/speakers/{slug}', function () use ($app) { // ...});

Ruta con partes variables

$app->get('/speakers/{slug}', function () use ($app) { // ...});

Ruta con partes variables

/speakers/pablo-garaizar/speakers/carlos-sanchez/speakers/esto-esta-mal

$app->post('/registro', function () use ($app) { // ...});

Otros métodos HTTP

$app->post('/registro', function () use ($app) { // ...});

Otros métodos HTTP

$app->put( );$app->delete( );

$app->match('/registro', function () use ($app) { // ...});

Ruta para todos los métodos HTTP

$app->match('/registro', function () use ($app) { // ...})->method('GET|POST');

Ruta para algunos métodos HTTP

$app->get('/speakers/{slug}', function ($slug) { // ...});

Rutas con variables

$app->get('/speakers/{track}/{slug}', function ($track, $slug) use ($app) { // ...});

Rutas con variables

use Symfony\Component\HttpFoundation\Request;

$app->get('/speakers/{slug}', function (Request $request, $slug) { // ...});

Variables especiales

use Symfony\Component\HttpFoundation\Request;

$app->get('/speakers/{slug}', function (Request $request, $slug) { // ...});

Variables especiales

use Symfony\Component\HttpFoundation\Request;

$app->get('/speakers/{slug}', function (Request $request, $slug) { // ...});

Variables especiales

$request->server->get('HTTP_USER_AGENT')$request->get('slug')

$app->get('/schedule/{slug}', function ($slug) use ($app) { // ...})->convert('slug', function ($slug) { return strtolower($slug);});

Modificando las variables de la ruta

$app->get('/schedule/{slug}', function ($slug) use ($app) { // ...})->convert('slug', function ($slug) { return str_replace('-', '_', $slug);});

Modificando las variables de la ruta

$app->get('/schedule/{track}', function ($track) { // ...})->assert('track', '\d+');

Restringiendo las variables de la ruta

$app->get('/schedule/{track}', function ($track) { // ...})->assert('track', 'track\d+');

Restringiendo las variables de la ruta

$app->get('/schedule/{track}', function ($track) { // ...})->assert('track', '1|2');

Restringiendo las variables de la ruta

$app->get('/schedule/{track}', function ($track) { // ...})->value('track', '1');

Valores por defecto

$app->get('/schedule/{track}', function ($track) { // ...})->value('track', '1');

Valores por defecto

/schedule/schedule/1

$app->get('/', function () use ($app) { // ...})->bind('portada');

Rutas con nombre

Controladores

$app->get('/donde-comer', function () use ($app) { return $app['twig']->render('comer.twig');})->bind('comer');

Controlador básico

$app->get('/', function () use ($app) { $ponentes = $app['ponentes'];

return $app['twig']->render('portada.twig', array('ponentes' => $ponentes) );})->bind('portada');

Controlador típico

$app->get('/', function () use ($app) { $ponentes = $app['ponentes'];

return $app['twig']->render('portada.twig', array('ponentes' => $ponentes) );})->bind('portada');

Controlador típico

$app->get('/speakers/{slug}', function ($slug) use ($app) {

if (...) { $app->abort(404, "No existe el ponente."); }

// ... return $app['twig']->render('ponente.twig',...);

})->bind('ponente');

Gestión de errores

$app->get('/speakers/{slug}', function ($slug) use ($app) {

if (...) { $app->abort(404, "No existe el ponente."); }

// ... return $app['twig']->render('ponente.twig',...);

})->bind('ponente');

Gestión de errores

$app->error(function (\Exception $e, $code) use ($app) {

// ...

});

Controlador especial para errores

$app->error(function (\Exception $e, $code) use ($app) {

// ...

});

Controlador especial para errores

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

Esqueleto de una aplicación Silex

1 aplicación = 1 archivo

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

controllers.php

1 aplicación = 1 archivo

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

controllers.php

EL ORDEN IMPORTA

Middlewares(filtros)

Petición HTTP

Tu aplicación

Página HTML

Objeto Request

Objeto Response

Silex

Silex

Petición HTTP

Tu aplicación

Página HTML

Objeto Request

Objeto Response

Silex

Silex

!

!

!

$app->before(function (Request $request) { // ...});

Filtro before

Secuencia de ejecución• Buscar la ruta que pide el usuario.

• Comprobar la seguridad.

• Ejecutar filtro before()

• Ejecutar controlador de la ruta

$app->before(function (Request $request) { if (...) { return new RedirectResponse('/login'); }});

Ejemplo de filtro before

$app->after(function (Request $request, Response $response) { // ...});

Filtro after

Secuencia de ejecución• Buscar la ruta que pide el usuario.

• Comprobar la seguridad.

• Ejecutar filtro before( )

• Ejecutar controlador de la ruta.

• Ejecutar filtro after( )

• Enviar respuesta al usuario.

$app->after(function (Request $request) { log('...');});

Ejemplo de filtro after

$app->after(function (Request $request) { log('...');});

Ejemplo de filtro after

¿Dónde está mi respuesta?

$app->finish(function (Request $request, Response $response) { // ...});

Filtro finish

$app->get('/', ...)->bind('portada')->before(...);

$app->get('/agenda', ...)->bind('agenda')->before(...)->after(...);

$app->get('/speakers/{slug}', ...)->bind('ponente')->before(...);

$app->get('/schedule/{slug}', ...)->bind('ponencia')->before(...);

Cada ruta con su filtro

Proveedores deservicios

Núcleo de Silex

Bases de datos

Plantillas

Caché HTTP

Envío de emails

Formularios

proveedores

Núcleo de Silex

Bases de datos

Plantillas

Caché HTTP

Envío de emails

Formularios

proveedores

Núcleo de Silex

Bases de datos

Plantillas

Caché HTTP

Envío de emails

Formularios

proveedores

Núcleo de Silex

Bases de datos

Plantillas

Caché HTTP

Envío de emails

Formularios

Bases de datos Serializador Seguridad

Formularios Logger Sesiones

Validación Emails Plantillas

Caché HTTP URL

use Silex\Provider\FormServiceProvider;

// ...

$app->register(new FormServiceProvider());

Usar formularios de Symfony2

use Silex\Provider\DoctrineServiceProvider;

// ...

$app->register(new DoctrineServiceProvider());

Acceder a BBDD con Doctrine2

use Silex\Provider\TwigServiceProvider;

// ...

$app->register(new TwigServiceProvider(), array( 'twig.path' => array(__DIR__.'/../templates'), 'twig.options' => array('...'),));

Utilizar las plantillas de Twig

DEMO

github.com/javiereguiluz/bilbostack

Fork me on GitH

ub

Instalación

Descargar archivo comprimido

silex.sensiolabs.org

Descargar archivo comprimido

Descargar archivo comprimido

Descargar archivo comprimido

{ "require": { "silex/silex": "1.0.*" }, "minimum-stability": "dev"}

Instalación via composer.json

{ "require": { "fabpot/silex-skeleton": "*" }, "minimum-stability": "dev"}

Instalación via composer.json

$ composer create-project fabpot/silex-skeleton --stability=dev

Instalación recomendada

web/index.php

src/app.php

src/controllers.php

web/index.php

src/app.php

src/controllers.php

No tocar

web/index.php

src/app.php

src/controllers.php

No tocar Activas servicios

web/index.php

src/app.php

src/controllers.php

No tocar Activas servicios

$app->get('/', ...});

Buenasprácticas

Organizandolos controladores

$app->get('/', ...);

blog.php

$app->get('/', ...);

backend.php

$app->get('/', ...);

// ...

controllers.php

$app->mount('/blog', include 'blog.php');$app->mount('/admin', include 'backend.php');

Importando controladores

$app->mount('/blog', include 'blog.php');$app->mount('/admin', include 'backend.php');

Importando controladores

$app->mount('/blog', include 'blog.php');$app->mount('/admin', include 'backend.php');

Importando controladores

PORTADA: /PORTADA DE BLOG: /blog/PORTADA DE BACKEND: /admin/

1 aplicación = 1 archivo

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

controllers.php

1 aplicación pequeña = 1 archivo

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

controllers.php

$app->get('/', ...);

$app->get('/ver', ...);

$app->get('/listar', ...);

$app->get('/', ...);

1 aplicación mediana = N archivos

$app->get('/', ...)->bind('portada');

$app->get('/agenda', ...)->bind('agenda');

$app->get('/speakers/{slug}', ...)->bind('ponente');

$app->get('/schedule/{slug}', ...)->bind('ponencia');

controllers.php

blog.php

backend.php

Escalando unaaplicación Silex

namespace Igorw\Shop\Controller;

use Silex\Application;use Symfony\Component\HttpFoundation\Request;

class ShopController{ public function indexAction(Request $request, Application $app) { ... }}

Controladores como clases

$app->get('/', controller('shop/index'));

$app->match('/login', controller('shop/login'));

$app->get('/product', controller('shop/

product'));

Controladores como clases

http://igor.io/2012/11/09/scaling-silex.html

Puntosdébiles

i18n Depuración

ORM Documentación

ESI

i18n (internacionalización)• Fácil traducir contenidos

{{ "Hola Mundo"|trans }}

• No es cómodo traducir rutas y contenidos de la base de datos.

ORM• No hay soporte oficial del ORM

completo (Doctrine2).

• No hay ORM alternativos ligeros.

• Si tu aplicación necesita un ORM, puede ser demasiado grande para Silex.

// activar el modo debug$app['debug'] = true;

// activar el loguse Silex\Provider\MonologServiceProvider;

$app->register(new MonologServiceProvider(), array( 'monolog.logfile' => __DIR__.'/../logs/dev.log',));

Depuración

Mensajes de error

ESI• Silex incluye soporte de ESI.

• Su uso es bastante incómodo (comparado con Symfony2).

Documentación• Todas las características de Silex

están documentadas.

• No es tan abundante como la de Symfony2.

Documentación• Oficial

silex.sensiolabs.org/documentation

• Traducciónlibrosweb.es/silex

Conclusiones

Conclusiones• Silex es un microframework, pero no es

un juguete.

Conclusiones• Silex es un microframework, pero no es

un juguete.

• Silex sirve para cualquier aplicación web que no sea enorme.

Conclusiones• Silex es un microframework, pero no es

un juguete.

• Silex sirve para cualquier aplicación web que no sea enorme.

• Silex reduce a “horas” el tiempo de desarrollo de aplicaciones enteras.

Conclusiones• Silex es un microframework, pero no es

un juguete.

• Silex sirve para cualquier aplicación web que no sea enorme.

• Silex reduce a “horas” el tiempo de desarrollo de aplicaciones enteras.

• Silex combina la agilidad de PHP con la profesionalidad de Symfony.

GRACIAS.