Silex, desarrollo web ágil y profesional con PHP
-
Upload
javier-eguiluz -
Category
Technology
-
view
13.326 -
download
4
description
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.
Contacto• [email protected]
• twitter.com/javiereguiluz
• github.com/javiereguiluz
• linkedin.com/in/javiereguiluz
domingo, 27 de enero de 13