symfony2 es rev2.0.12

797
Symfony2-es Release 2.0.12 Traducido por Nacho Pacheco April 24, 2012

Upload: juan-carlos-rojas-toralva

Post on 22-Oct-2015

224 views

Category:

Documents


10 download

TRANSCRIPT

  • Symfony2-esRelease 2.0.12

    Traducido por Nacho Pacheco

    April 24, 2012

  • ndice general

    I Gua de inicio rpido 1

    1. Inicio rpido 51.1. Un primer vistazo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2. La vista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.3. El controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171.4. La arquitectura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

    II Libro 29

    2. Libro 332.1. Symfony2 y fundamentos HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.2. Symfony2 frente a PHP simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422.3. Instalando y configurando Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532.4. Creando pginas en Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572.5. Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712.6. Enrutando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812.7. Creando y usando plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992.8. Bases de datos y Doctrine (El modelo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1182.9. Bases de datos y Propel (El modelo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1412.10. Probando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1482.11. Validando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1602.12. Formularios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1732.13. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1982.14. Cach HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2282.15. Traduciendo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2422.16. Contenedor de servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2562.17. Rendimiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2722.18. Funcionamiento interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2742.19. API estable de Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

    I

  • III Recetario 287

    3. Recetario 2893.1. Flujo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2893.2. Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2943.3. Enrutando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2963.4. Assetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2983.5. Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3133.6. Formularios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3283.7. Validando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3633.8. Configurando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3653.9. Contenedor de servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3763.10. Paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3953.11. Correo electrnico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4093.12. Probando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4163.13. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4223.14. Almacenamiento en cach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4673.15. Plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4693.16. Bitcora de navegacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4753.17. Consola . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4823.18. Cmo optimizar tu entorno de desarrollo para depuracin . . . . . . . . . . . . . . . . . . . . . . . 4833.19. Despachador de eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4843.20. Peticin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4873.21. Generador de perfiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4893.22. Servicios web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4913.23. En qu difiere Symfony2 de symfony1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494

    IV Componentes 503

    4. Componentes 5054.1. El componente ClassLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5054.2. El componente Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5074.3. El componente CssSelector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5124.4. El componente DomCrawler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5144.5. Inyeccin de dependencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5194.6. Despachador de eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5234.7. El componente Finder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5354.8. Fundamento HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5384.9. El componente Locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5544.10. El componente Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5554.11. El componente Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5564.12. El componente Templating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5614.13. El componente YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563

    V Documentos de referencia 571

    5. Documentos de referencia 5755.1. Configurando el FrameworkBundle (framework) . . . . . . . . . . . . . . . . . . . . . . . . . 5755.2. Referencia de configuracin de AsseticBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . 5805.3. Referencia de configuracin del ORM de Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . 5815.4. Referencia en configurando Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5865.5. Configurando el SwiftmailerBundle ("swiftmailer") . . . . . . . . . . . . . . . . . . . . 5895.6. Referencia de configuracin de TwigBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592

    II

  • 5.7. Referencia de configuracin del ORM de Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . 5945.8. Configurando WebProfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5955.9. Referencia de tipos para formulario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5965.10. Referencia de funciones de formulario en plantillas Twig . . . . . . . . . . . . . . . . . . . . . . . . 6575.11. Referencia de restricciones de validacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6585.12. Etiquetas de inyeccin de dependencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7145.13. Requisitos para que funcione Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719

    VI Paquetes 723

    6. Paquetes de la edicin estndar de Symfony 7276.1. SensioFrameworkExtraBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7276.2. SensioGeneratorBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7366.3. DoctrineFixturesBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7396.4. DoctrineMigrationsBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7446.5. DoctrineMongoDBBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749

    VII Colaborando 769

    7. Colaborando 7737.1. Aportando cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7737.2. Aportando documentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7837.3. Comunidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 789

    III

  • IV

  • Parte I

    Gua de inicio rpido

    1

  • Symfony2-es, Release 2.0.12

    Empieza a trabajar rpidamente con la Gua de inicio rpido (Pgina 5) de Symfony:

    3

  • Symfony2-es, Release 2.0.12

    4

  • CAPTULO 1

    Inicio rpido

    1.1 Un primer vistazo

    Empieza a usar Symfony2 en 10 minutos! Este captulo te guiar a travs de algunos de los conceptos ms importantesdetrs de Symfony2 y explica cmo puedes empezar a trabajar rpidamente, mostrndote un sencillo proyecto enaccin.

    Si ya has usado una plataforma para desarrollo web, seguramente te sentirs a gusto con Symfony2. Si no es tu caso,bienvenido a una nueva forma de desarrollar aplicaciones web!

    Truco: Quieres saber por qu y cundo es necesario utilizar una plataforma? Lee el documento Symfony en 5minutos.

    1.1.1 Descargando Symfony2

    En primer lugar, comprueba que tienes instalado y configurado un servidor web (como Apache) con PHP 5.3.2 osuperior.

    Listo? Empecemos descargando la edicin estndar de Symfony2, una distribucin de Symfony preconfiguradapara la mayora de los casos y que tambin contiene algn cdigo de ejemplo que demuestra cmo utilizar Symfony2(consigue el paquete que incluye proveedores para empezar an ms rpido).

    Despus de extraer el paquete bajo el directorio raz del servidor web, deberas tener un directorio Symfony/ conuna estructura como esta:

    www/

  • Symfony2-es, Release 2.0.12

    Resources/...

    vendor/symfony/doctrine/...

    web/app.php...

    Nota: Si descargaste la edicin estndar sin vendors, basta con ejecutar la siguiente orden para descargar todaslas bibliotecas de proveedores:

    curl -s http://getcomposer.org/installer | php

    php composer.phar install

    Si no tienes instalado curl, simplemente puedes descargar manualmente el archivo instalador dehttp://getcomposer.org/installer. Coloca ese archivo en tu proyecto y luego ejecuta:

    php installerphp composer.phar install

    1.1.2 Verificando tu configuracin

    Symfony2 integra una interfaz visual para probar la configuracin del servidor, muy til para solucionar problemasrelacionados con el servidor Web o una incorrecta configuracin de PHP. Usa la siguiente url para examinar el diag-nstico:

    http://localhost/Symfony/web/config.php

    Si se listan errores o aspectos de configuracin pendientes, corrgelos; Puedes realizar los ajustes siguiendo las reco-mendaciones. Cuando todo est bien, haz clic en Pospn la configuracin y llvame a la pgina de bienvenida parasolicitar tu primera pgina web real en Symfony2:

    http://localhost/Symfony/web/app_dev.php/

    Symfony2 debera darte la bienvenida y felicitarte por tu arduo trabajo hasta el momento!

    6 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    1.1.3 Comprendiendo los fundamentos

    Uno de los principales objetivos de una plataforma es garantizar la separacin de responsabilidades. Esto mantiene tucdigo organizado y permite a tu aplicacin evolucionar fcilmente en el tiempo, evitando mezclar llamadas a la basede datos, etiquetas HTML y cdigo de la lgica del negocio en un mismo archivo. Para alcanzar este objetivo, debesaprender algunos conceptos y trminos fundamentales.

    Truco: Quieres ms pruebas de que usar una plataforma es mucho mejor que mezclar todo en un mismo archivo?Lee el captulo del libro Symfony2 frente a PHP simple (Pgina 42).

    La distribucin viene con algn cdigo de ejemplo que puedes utilizar para aprender ms sobre los principales con-ceptos de Symfony2. Ingresa a la siguiente URL para recibir un saludo de Symfony2 (reemplaza Nacho con tu nombre):

    http://localhost/Symfony/web/app_dev.php/demo/hello/Nacho

    1.1. Un primer vistazo 7

  • Symfony2-es, Release 2.0.12

    Qu sucedi? Bien, diseccionemos la URL:

    app_dev.php: Es un controlador frontal. Es el nico punto de entrada de la aplicacin, mismo que respondea todas las peticiones del usuario;

    /demo/hello/Nacho: Esta es la ruta virtual a los recursos que el usuario quiere acceder.

    Tu responsabilidad como desarrollador es escribir el cdigo que asigna la peticin del usuario(/demo/hello/Nacho) al recurso asociado con ella (la pgina HTML Hola Nacho!).

    Enrutando

    Symfony2 encamina la peticin al cdigo que la maneja tratando de hacer coincidir la URL solicitada contra algunospatrones configurados. De forma predeterminada, estos patrones (llamados rutas) se definen en el archivo de configu-racin app/config/routing.yml: Cuando ests en el entorno (Pgina 11) dev indicado por el controladorfrontal app_dev.php tambin se carga el archivo de configuracin app/config/routing_dev.yml. En laedicin estndar, las rutas a estas pginas de demostracin se encuentran en ese archivo:

    # app/config/routing_dev.yml_welcome:

    pattern: /defaults: { _controller: AcmeDemoBundle:Welcome:index }

    _demo:resource: "@AcmeDemoBundle/Controller/DemoController.php"type: annotationprefix: /demo

    # ...

    Las primeras tres lneas (despus del comentario) definen el cdigo que se ejecuta cuando el usuario solicita elrecurso / (es decir, la pgina de bienvenida que viste anteriormente). Cuando as lo solicites, el controladorAcmeDemoBundle:Welcome:index ser ejecutado. En la siguiente seccin, aprenders exactamente lo que esosignifica.

    8 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    Truco: La edicin estndar de Symfony2 utiliza YAML para sus archivos de configuracin, pero Symfony2 tambines compatible con XML, PHP y anotaciones nativas. Los diferentes formatos son compatibles y se pueden utilizarindistintamente en una aplicacin. Adems, el rendimiento de tu aplicacin no depende del formato de configuracinque elijas, ya que todo se memoriza en cach en la primer peticin.

    Controladores

    Controlador es un nombre elegante para una funcin o mtodo PHP que se encarga de laspeticiones entrantes y devuelve las respuestas (a menudo cdigo HTML). En lugar de utili-zar variables globales y funciones PHP (como $_GET o header()) para manejar estos men-sajes HTTP, Symfony utiliza objetos: Symfony\Component\HttpFoundation\Request ySymfony\Component\HttpFoundation\Response. El controlador ms simple posible crea la respuesta amano, basndose en la peticin:

    use Symfony\Component\HttpFoundation\Response;

    $name = $request->query->get(name);

    return new Response(Hello .$name, 200, array(Content-Type => text/plain));

    Nota: Symfony2 abarca la especificacin HTTP, esta contiene las reglas que gobiernan todas las comunicaciones enla web. Lee el captulo Symfony2 y fundamentos HTTP (Pgina 33) del libro para aprender ms acerca de esto y lapotencia que ello conlleva.

    Symfony2 elige el controlador basndose en el valor del _controller de la configuracin de enrutado:AcmeDemoBundle:Welcome:index. Esta cadena es el nombre lgico del controlador, y hace referencia al m-todo indexAction de la clase Acme\DemoBundle\Controller\WelcomeController:

    // src/Acme/DemoBundle/Controller/WelcomeController.phpnamespace Acme\DemoBundle\Controller;

    use Symfony\Bundle\FrameworkBundle\Controller\Controller;

    class WelcomeController extends Controller{

    public function indexAction(){

    return $this->render(AcmeDemoBundle:Welcome:index.html.twig);}

    }

    Truco: Podras haber usado el nombre completo de la clase y mtodo Acme\DemoBundle\Controller\WelcomeController::indexAction para el valor del_controller. Pero si sigues algunas simples convenciones, el nombre lgico es ms conciso y te permitemayor flexibilidad.

    La clase WelcomeController extiende la clase integrada Controller, la cual proporciona tiles atajos amtodos, como el :method:Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render que carga yreproduce una plantilla (AcmeDemoBundle:Welcome:index.html.twig). El valor devuelto es un objetoRespuesta poblado con el contenido reproducido. Por lo tanto, si surge la necesidad, la Respuesta se puedeajustar antes de enviarla al navegador:

    1.1. Un primer vistazo 9

  • Symfony2-es, Release 2.0.12

    public function indexAction(){

    $response = $this->render(AcmeDemoBundle:Welcome:index.txt.twig);$response->headers->set(Content-Type, text/plain);

    return $response;}

    Pero en todos los casos, el trabajo final del controlador es devolver siempre el objeto Respuesta que ser entregadoal usuario. Este objeto Respuesta se puede poblar con cdigo HTML, representar una redireccin al cliente, eincluso devolver el contenido de una imagen JPG con una cabecera Content-Type de image/jpg.

    Truco: Derivar de la clase base Controller es opcional. De hecho, un controlador puede ser una simple funcinPHP e incluso un cierre PHP. El captulo Controlador (Pgina 71) del libro abarca todo sobre los controladores deSymfony2.

    El nombre de la plantilla, AcmeDemoBundle:Welcome:index.html.twig, es el nombre lgico de la plantillay hace referencia al archivo Resources/views/Welcome/index.html.twig dentro del AcmeDemoBundle(ubicado en src/Acme/DemoBundle). En la seccin paquetes, a continuacin, explicar por qu esto es til.

    Ahora, de nuevo echa un vistazo a la configuracin de enrutado y encuentra la clave _demo:

    # app/config/routing_dev.yml_demo:

    resource: "@AcmeDemoBundle/Controller/DemoController.php"type: annotationprefix: /demo

    Symfony2 puede leer/importar la informacin de enrutado desde diferentes archivos escritos en YAML,XML, PHP o, incluso, incorporada en anotaciones PHP. En este caso, el nombre lgico del re-curso es @AcmeDemoBundle/Controller/DemoController.php y se refiere al archivosrc/Acme/DemoBundle/Controller/DemoController.php. En este archivo, las rutas se definencomo anotaciones sobre los mtodos de accin:

    // src/Acme/DemoBundle/Controller/DemoController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

    class DemoController extends Controller{

    /*** @Route("/hello/{name}", name="_demo_hello")

    * @Template()

    */public function helloAction($name){

    return array(name => $name);}

    // ...}

    La anotacin @Route() define una nueva ruta con un patrn de /hello/{name} que ejecuta el mtodohelloAction cuando concuerda. Una cadena encerrada entre llaves como {name} se conoce como marcadorde posicin. Como puedes ver, su valor se puede recuperar a travs del argumento $name del mtodo.

    Nota: Incluso si las anotaciones no son compatibles nativamente en PHP, las utilizamos ampliamente en Symfony2

    10 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    como una conveniente manera de configurar el comportamiento de la plataforma y mantener la configuracin del ladodel cdigo.

    Si echas un vistazo ms de cerca al cdigo de la accin del controlador, puedes ver que en lugar de re-producir una plantilla y devolver un objeto Respuesta como antes, slo devuelve una matriz de parme-tros. La anotacin @Template() le dice a Symfony que reproduzca la plantilla por ti, pasando cada varia-ble del arreglo a la plantilla. El nombre de la plantilla reproducida sigue al nombre del controlador. Por lotanto, en este ejemplo, se reproduce la plantilla AcmeDemoBundle:Demo:hello.html.twig (ubicada ensrc/Acme/DemoBundle/Resources/views/Demo/hello.html.twig).

    Truco: Las anotaciones @Route() y @Template() son ms poderosas que lo mostrado en el ejemplo simple deesta gua. Aprende ms sobre las anotaciones en controladores en la documentacin oficial.

    Plantillas

    El controlador procesa la plantilla src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig(o AcmeDemoBundle:Demo:hello.html.twig si utilizas el nombre lgico):

    {# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #}{% extends "AcmeDemoBundle::base.html.twig" %}

    {% block title "Hello " ~ name %}

    {% block content %}Hello {{ name }}!

    {% endblock %}

    Por omisin, Symfony2 utiliza Twig como motor de plantillas, pero tambin puede utilizar plantillas PHP tradicionalessi lo deseas. El siguiente captulo es una introduccin a cmo trabajan las plantillas en Symfony2.

    Paquetes

    Posiblemente te hayas preguntado por qu la palabra bundle (paquete en adelante), se utiliza en muchos de los nombresque hemos visto hasta ahora. Todo el cdigo que escribas para tu aplicacin est organizado en paquetes. Hablando enSymfony2, un paquete es un conjunto estructurado de archivos (archivos PHP, hojas de estilo, JavaScript, imgenes,...) que implementa una sola caracterstica (un blog, un foro, ...) y que fcilmente se puede compartir con otros desa-rrolladores. Hasta ahora, hemos manipulado un paquete, AcmeDemoBundle. Aprenders ms acerca de los paquetesen el ltimo captulo de esta gua.

    1.1.4 Trabajando con entornos

    Ahora que tienes una mejor comprensin de cmo funciona Symfony2, dale una mirada ms atenta a la parte inferiorde cualquier pgina reproducida por Symfony2. Debers notar una pequea barra con el logotipo de Symfony2. Esta seconoce como la barra de depuracin web y es la mejor amiga del desarrollador.

    1.1. Un primer vistazo 11

  • Symfony2-es, Release 2.0.12

    Pero lo que ves al principio es slo la punta del iceberg; haz clic en el extrao nmero hexadecimal para revelar otramuy til herramienta de depuracin de Symfony2: el generador de perfiles.

    Por supuesto, no querrs mostrar estas herramientas al desplegar tu aplicacin en produccin. Es por eso que encontra-rs otro controlador frontal en el directorio web/ (app.php), el cual est optimizado para el entorno de produccin:

    http://localhost/Symfony/web/app.php/demo/hello/Nacho

    Y si utilizas Apache con mod_rewrite habilitado, incluso puedes omitir la parte app.php de la URL:

    http://localhost/Symfony/web/demo/hello/Nacho

    Por ltimo pero no menos importante, en los servidores en produccin, debes apuntar tu directorio web raz al direc-torio web/ para proteger tu instalacin e incluso, para que tus URL tengan un mejor aspecto:

    12 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    http://localhost/demo/hello/Nacho

    Nota: Ten en cuenta que las tres direcciones URL anteriores slo se proporcionan aqu como ejemplos de cmo se veuna URL al utilizar el controlador frontal de produccin (con o sin mod_rewrite). Si realmente lo intentas en unainstalacin de la edicin estndar de Symfony, fuera de la caja obtendrs un error 404 puesto que AcmeDemoBundleslo se activa en el entorno de desarrollo e importa sus rutas en app/config/routing_dev.yml.

    Para hacer que la aplicacin responda ms rpido, Symfony2 mantiene una cach en el directorio app/cache/.En el entorno de desarrollo (app_dev.php), esta cach se vaca automticamente cada vez que realizas cambios encualquier cdigo o configuracin. Pero ese no es el caso en el entorno de produccin (app.php) donde el rendimientoes clave. Es por eso que siempre debes utilizar el entorno de desarrollo al estar desarrollando tu aplicacin.

    Diferentes entornos de una determinada aplicacin slo se diferencian en su configuracin. De hecho, una configura-cin puede heredar de otra:

    # app/config/config_dev.ymlimports:

    - { resource: config.yml }

    web_profiler:toolbar: trueintercept_redirects: false

    El entorno dev (el cual carga el archivo de configuracin config_dev.yml) importa el archivo globalconfig.yml y luego lo modifica, en este ejemplo, activando la barra de herramientas para depuracin web.

    1.1.5 Consideraciones finales

    Enhorabuena! Has tenido tu primera experiencia codificando en Symfony2. No fue tan difcil, cierto? Hay muchoms por explorar, pero ya debes tener una idea de cmo Symfony2 facilita la implementacin de mejores y ms rpidossitios web. Si ests interesado en aprender ms acerca de Symfony2, sumrgete en la siguiente seccin: La vista(Pgina 13).

    1.2 La vista

    Despus de leer la primera parte de esta gua, has decidido que bien valen la pena otros 10 minutos en Symfony2.Buena eleccin! En esta segunda parte, aprenders ms sobre el motor de plantillas de Symfony2, Twig. Twig es unmotor de plantillas flexible, rpido y seguro para PHP. Este hace tus plantillas ms legibles y concisas; adems dehacerlas ms amigables para los diseadores web.

    Nota: En lugar de Twig, tambin puedes utilizar PHP (Pgina 469) para tus plantillas. Ambos motores de plantillasson compatibles con Symfony2.

    1.2.1 Familiarizndote con Twig

    Truco: Si quieres aprender Twig, te recomendamos que leas la documentacin oficial. Esta seccin es slo unadescripcin rpida de los conceptos principales.

    1.2. La vista 13

  • Symfony2-es, Release 2.0.12

    Una plantilla Twig es un archivo de texto que puede generar cualquier tipo de contenido (HTML, XML, CSV, LaTeX,...). Twig define dos tipos de delimitadores:

    {{ ... }}: Imprime una variable o el resultado de una expresin;

    {% ...%}: Controla la lgica de la plantilla; se utiliza para ejecutar bucles for y declaraciones if, porejemplo.

    A continuacin mostramos una plantilla mnima que ilustra algunos conceptos bsicos, usando dos variablespage_title y navigation, las cuales se deben pasar a la plantilla:

    {{ page_title }}

    {{ page_title }}

    {% for item in navigation %}

    {{ item.caption }}{% endfor %}

    Truco: Puedes incluir comentarios dentro de las plantillas con el delimitador {# ... #}.

    Para reproducir una plantilla en Symfony, utiliza el mtodo render dentro de un controlador, suministrando cualquiervariable necesaria en la plantilla:

    $this->render(AcmeDemoBundle:Demo:hello.html.twig, array(name => $name,

    ));

    Las variables pasadas a una plantilla pueden ser cadenas, matrices e incluso objetos. Twig abstrae la diferencia entreellas y te permite acceder a los atributos de una variable con la notacin de punto (.):

    {# array(name => Fabien) #}{{ name }}

    {# array(user => array(name => Fabien)) #}{{ user.name }}

    {# obliga a verlo como arreglo #}{{ user[name] }}

    {# array(user => new User(Fabien)) #}{{ user.name }}{{ user.getName }}

    {# obliga a ver el nombre como mtodo #}{{ user.name() }}{{ user.getName() }}

    {# pasa argumentos al mtodo #}{{ user.date(Y-m-d) }}

    14 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    Nota: Es importante saber que las llaves no son parte de la variable, sino de la declaracin de impresin. Si accedesa variables dentro de las etiquetas no las envuelvas con llaves.

    Decorando plantillas

    Muy a menudo, las plantillas en un proyecto comparten elementos comunes, como los bien conocidos encabezadosy pies de pgina. En Symfony2, nos gusta pensar en este problema de forma diferente: una plantilla se puede decorarcon otra. Esto funciona exactamente igual que las clases PHP: La herencia de plantillas te permite crear un esque-leto de plantilla base que contenga todos los elementos comunes de tu sitio y define los bloques que las plantillasdescendientes pueden sustituir.

    La plantilla hello.html.twig hereda de base.html.twig, gracias a la etiqueta extends:

    {# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #}{% extends "AcmeDemoBundle::base.html.twig" %}

    {% block title "Hello " ~ name %}

    {% block content %}Hello {{ name }}!

    {% endblock %}

    La notacin AcmeDemoBundle::base.html.twig suena familiar, no? Es la misma notacin utilizada parahacer referencia a una plantilla regular. La parte :: simplemente significa que el elemento controlador est vaco, porlo tanto el archivo correspondiente se almacena directamente bajo el directorio Resources/views/.

    Ahora, echemos un vistazo a un base.html.twig simplificado:

    {# src/Acme/DemoBundle/Resources/views/base.html.twig #}

    {% block content %}{% endblock %}

    La etiqueta {% block%} define bloques que las plantillas derivadas pueden llenar. Todas las etiquetas de bloque ledicen al motor de plantillas que una plantilla derivada puede reemplazar esas porciones de la plantilla.

    En este ejemplo, la plantilla hello.html.twig sustituye el bloque content, lo cual significa que el texto"Hello Fabien" se reproduce dentro del elemento div.symfony-content.

    Usando etiquetas, filtros y funciones

    Una de las mejores caractersticas de Twig es su extensibilidad a travs de etiquetas, filtros y funciones. Symfony2viene empacado con muchas de estas integradas para facilitar el trabajo del diseador de la plantilla.

    Incluyendo otras plantillas

    La mejor manera de compartir un fragmento de cdigo entre varias plantillas diferentes es crear una nueva plantilla,que luego puedas incluir en otras plantillas.

    Crea una plantilla embedded.html.twig:

    {# src/Acme/DemoBundle/Resources/views/Demo/embedded.html.twig #}Hello {{ name }}

    1.2. La vista 15

  • Symfony2-es, Release 2.0.12

    Y cambia la plantilla index.html.twig para incluirla:

    {# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #}{% extends "AcmeDemoBundle::base.html.twig" %}

    {# sustituye el bloque content por embedded.html.twig #}{% block content %}

    {% include "AcmeDemoBundle:Demo:embedded.html.twig" %}{% endblock %}

    Integrando otros controladores

    Y si deseas incrustar el resultado de otro controlador en una plantilla? Eso es muy til cuando se trabaja con Ajax, ocuando la plantilla incrustada necesita alguna variable que no est disponible en la plantilla principal.

    Supongamos que has creado una accin fancy, y deseas incluirla dentro de la plantilla index principal. Para ello,utiliza la etiqueta render:

    {# src/Acme/DemoBundle/Resources/views/Demo/index.html.twig #}{% render "AcmeDemoBundle:Demo:fancy" with { name: name, color: green } %}

    Aqu, la cadena AcmeDemoBundle:Demo:fancy se refiere a la accin fancy del controlador Demo. Los argu-mentos (name y color) actan como variables de la peticin simulada (como si fancyAction estuviera manejan-do una peticin completamente nueva) y se ponen a disposicin del controlador:

    // src/Acme/DemoBundle/Controller/DemoController.php

    class DemoController extends Controller{

    public function fancyAction($name, $color){

    // crea algn objeto, basndose en la variable $color$object = ...;

    return $this->render(AcmeDemoBundle:Demo:fancy.html.twig, array(name => $name, object => $object));}

    // ...}

    Creando enlaces entre pginas

    Hablando de aplicaciones web, forzosamente tienes que crear enlaces entre pginas. En lugar de codificar las URL enlas plantillas, la funcin path sabe cmo generar URL basndose en la configuracin de enrutado. De esta manera,todas tus URL se pueden actualizar fcilmente con slo cambiar la configuracin:

    Greet Thomas!

    La funcin path toma el nombre de la ruta y una matriz de parmetros como argumentos. El nombre de la ruta es laclave principal en la cual se hace referencia a las rutas y los parmetros son los valores de los marcadores de posicindefinidos en el patrn de la ruta:

    // src/Acme/DemoBundle/Controller/DemoController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

    16 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    /*** @Route("/hello/{name}", name="_demo_hello")

    * @Template()

    */public function helloAction($name){

    return array(name => $name);}

    Truco: La funcin url genera URL absolutas: {{ url(_demo_hello, { name: Thomas }) }}.

    Incluyendo activos: imgenes, JavaScript y hojas de estilo

    Qu sera de Internet sin imgenes, JavaScript y hojas de estilo? Symfony2 proporciona la funcin asset parahacerles frente fcilmente:

    El propsito principal de la funcin asset es hacer ms porttil tu aplicacin. Gracias a esta funcin, puedes moverel directorio raz de la aplicacin a cualquier lugar bajo tu directorio web raz sin cambiar nada en el cdigo de tusplantillas.

    Escapando variables

    Twig est configurado para escapar toda su produccin automticamente. Lee la documentacin de Twig para obtenerms informacin sobre el mecanismo de escape y la extensin Escaper.

    Consideraciones finales

    Twig es simple pero potente. Gracias a los diseos, bloques, plantillas e inclusin de acciones, es muy fcil organizartus plantillas de manera lgica y extensible. Sin embargo, si no te sientes cmodo con Twig, siempre puedes utilizarlas plantillas de PHP dentro de Symfony sin ningn problema.

    Slo has estado trabajando con Symfony2 durante unos 20 minutos, pero ya puedes hacer cosas muy sorprendentescon l. Ese es el poder de Symfony2. Aprender los conceptos bsicos es fcil, y pronto aprenders que esta simplicidadest escondida bajo una arquitectura muy flexible.

    Pero me estoy adelantando demasiado. En primer lugar, necesitas aprender ms sobre el controlador y ese exactamentees el tema de la siguiente parte de esta gua (Pgina 17). Listo para otros 10 minutos con Symfony2?

    1.3 El controlador

    Todava con nosotros despus de las dos primeras partes? Ya te ests volviendo adicto a Symfony2! Sin ms prem-bulos, vamos a descubrir lo que los controladores pueden hacer por ti.

    1.3. El controlador 17

  • Symfony2-es, Release 2.0.12

    1.3.1 Usando Formatos

    Hoy da, una aplicacin web debe ser capaz de ofrecer algo ms que solo pginas HTML. Desde XML para alimenta-dores RSS o Servicios Web, hasta JSON para peticiones Ajax, hay un montn de formatos diferentes a elegir. Apoyarestos formatos en Symfony2 es sencillo. Modifica la ruta aadiendo un valor predeterminado de xml a la variable_format:

    // src/Acme/DemoBundle/Controller/DemoController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

    /*** @Route("/hello/{name}", defaults={"_format"="xml"}, name="_demo_hello")

    * @Template()

    */public function helloAction($name){

    return array(name => $name);}

    Al utilizar el formato de la peticin (como lo define el valor _format), Symfony2 automticamente selecciona laplantilla adecuada, aqu hello.xml.twig:

    {{ name }}

    Eso es todo lo que hay que hacer. Para los formatos estndar, Symfony2 tambin elije automticamente la mejorcabecera Content-Type para la respuesta. Si quieres apoyar diferentes formatos para una sola accin, en su lugar,usa el marcador de posicin {_format} en el patrn de la ruta:

    // src/Acme/DemoBundle/Controller/DemoController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

    /*** @Route("/hello/{name}.{_format}", defaults={"_format"="html"}, requirements={"_format"="html|xml|json"}, name="_demo_hello")

    * @Template()

    */public function helloAction($name){

    return array(name => $name);}

    El controlador ahora ser llamado por la URL como /demo/hello/Fabien.xml o/demo/hello/Fabien.json.

    La entrada requirements define las expresiones regulares con las cuales los marcadores de posicin deben coinci-dir. En este ejemplo, si tratas de solicitar el recurso /demo/hello/Fabien.js, obtendrs un error HTTP 404, yaque no coincide con el requisito de _format.

    1.3.2 Redirigiendo y reenviando

    Si deseas redirigir al usuario a otra pgina, utiliza el mtodo redirect():

    return $this->redirect($this->generateUrl(_demo_hello, array(name => Lucas)));

    18 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    El mtodo generateUrl() es el mismo que la funcin path() que utilizamos en las plantillas. Este toma elnombre de la ruta y una serie de parmetros como argumentos y devuelve la URL amigable asociada.

    Adems, fcilmente puedes reenviar a otra accin con el mtodo forward(). Internamente, Symfony hace unasubpeticin, y devuelve el objeto Respuesta desde la subpeticin:

    $response = $this->forward(AcmeDemoBundle:Hello:fancy, array(name => $name, color => green));

    // hace algo con la respuesta o la devuelve directamente

    1.3.3 Obteniendo informacin de la peticin

    Adems del valor de los marcadores de posicin de enrutado, el controlador tambin tiene acceso al objeto Peticin:

    $request = $this->getRequest();

    $request->isXmlHttpRequest(); // es una peticin Ajax?

    $request->getPreferredLanguage(array(en, fr));

    $request->query->get(page); // obtiene un parmetro $_GET

    $request->request->get(page); // obtiene un parmetro $_POST

    En una plantilla, tambin puedes acceder al objeto Peticin por medio de la variable app.request:

    {{ app.request.query.get(pag) }}

    {{ app.request.parameter(pag) }}

    1.3.4 Persistiendo datos en la sesin

    Aunque el protocolo HTTP es sin estado, Symfony2 proporciona un agradable objeto sesin que representa al cliente(sea una persona real usando un navegador, un robot o un servicio web). Entre dos peticiones, Symfony2 almacena losatributos en una cookie usando las sesiones nativas de PHP.

    Almacenar y recuperar informacin de la sesin se puede conseguir fcilmente desde cualquier controlador:

    $session = $this->getRequest()->getSession();

    // guarda un atributo para reutilizarlo durante una posterior peticin del usuario$session->set(foo, bar);

    // en otro controlador por otra peticin$foo = $session->get(foo);

    // usa un valor predefinido de no existir la clave$filters = $session->set(filters, array());

    Tambin puedes almacenar pequeos mensajes que slo estarn disponibles para la siguiente peticin:

    // guarda un mensaje para la siguiente peticin (en un controlador)$session->setFlash(notice, Congratulations, your action succeeded!);

    // muestra el mensaje de nuevo en la siguiente peticin (en una plantilla){{ app.session.flash(notice) }}

    1.3. El controlador 19

  • Symfony2-es, Release 2.0.12

    Esto es til cuando es necesario configurar un mensaje de xito antes de redirigir al usuario a otra pgina (la cualentonces mostrar el mensaje).

    1.3.5 Protegiendo recursos

    La edicin estndar de Symfony viene con una configuracin de seguridad sencilla, adaptada a las necesidades mscomunes:

    # app/config/security.ymlsecurity:

    encoders:Symfony\Component\Security\Core\User\User: plaintext

    role_hierarchy:ROLE_ADMIN: ROLE_USERROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:in_memory:

    memory:users:

    user: { password: userpass, roles: [ ROLE_USER ] }admin: { password: adminpass, roles: [ ROLE_ADMIN ] }

    firewalls:dev:

    pattern: ^/(_(profiler|wdt)|css|images|js)/security: false

    login:pattern: ^/demo/secured/login$security: false

    secured_area:pattern: ^/demo/secured/form_login:

    check_path: /demo/secured/login_checklogin_path: /demo/secured/login

    logout:path: /demo/secured/logouttarget: /demo/

    Esta configuracin requiere que los usuarios inicien sesin para cualquier URL que comience con /demo/secured/y define dos usuarios vlidos: user y admin. Por otra parte, el usuario admin tiene un rol ROLE_ADMIN, el cualincluye el rol ROLE_USER tambin (consulta el ajuste role_hierarchy).

    Truco: Para facilitar la lectura, las contraseas se almacenan en texto plano en esta configuracin simple, pero puedesusar cualquier algoritmo de codificacin ajustando la seccin encoders.

    Al ir a la direccin http://localhost/Symfony/web/app_dev.php/demo/secured/hello autom-ticamente redirigir al formulario de acceso, porque el recurso est protegido por un cortafuegos.

    Tambin puedes forzar la accin para exigir un determinado rol usando la anotacin @Secure en el controlador:

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use JMS\SecurityExtraBundle\Annotation\Secure;

    20 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    /*** @Route("/hello/admin/{name}", name="_demo_secured_hello_admin")

    * @Secure(roles="ROLE_ADMIN")

    * @Template()

    */public function helloAdminAction($name){

    return array(name => $name);}

    Ahora, inicia sesin como user (el cual no tiene el rol ROLE_ADMIN) y desde la pgina protegida hello, haz clicen el enlace Hola recurso protegido. Symfony2 debe devolver un cdigo de estado HTTP 403, el cual indica que elusuario tiene prohibido el acceso a ese recurso.

    Nota: La capa de seguridad de Symfony2 es muy flexible y viene con muchos proveedores de usuario diferentes (porejemplo, uno para el ORM de Doctrine) y proveedores de autenticacin (como HTTP bsica, HTTP digest o certifica-dos X509). Lee el captulo Seguridad (Pgina 198) del libro para ms informacin en cmo se usa y configura.

    1.3.6 Memorizando recursos en cach

    Tan pronto como tu sitio web comience a generar ms trfico, tendrs que evitar se genere el mismo recurso unay otra vez. Symfony2 utiliza cabeceras de cach HTTP para administrar los recursos en cach. Para estrategias dememorizacin en cach simples, utiliza la conveniente anotacin @Cache():

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;

    /*** @Route("/hello/{name}", name="_demo_hello")

    * @Template()

    * @Cache(maxage="86400")

    */public function helloAction($name){

    return array(name => $name);}

    En este ejemplo, el recurso se mantiene en cach por un da. Pero tambin puedes utilizar validacin en lugar decaducidad o una combinacin de ambas, si se ajusta mejor a tus necesidades.

    El recurso memorizado en cach es gestionado por el delegado inverso integrado en Symfony2. Pero debido a que lamemorizacin en cach se gestiona usando cabeceras de cach HTTP, puedes reemplazar el delegado inverso integra-do, con Varnish o Squid y escalar tu aplicacin fcilmente.

    Nota: Pero qu pasa si no puedes guardar en cach todas las pginas? Symfony2 todava tiene la solucin va ESI(Edge Side Includes o Inclusin de borde lateral), con la cual es compatible nativamente. Consigue ms informacinleyendo el captulo Cach HTTP (Pgina 228) del libro.

    1.3. El controlador 21

  • Symfony2-es, Release 2.0.12

    1.3.7 Consideraciones finales

    Eso es todo lo que hay que hacer, y ni siquiera estoy seguro de que hayan pasado los 10 minutos completos. Presen-tamos brevemente los paquetes en la primera parte, y todas las caractersticas que hemos explorado hasta ahora sonparte del paquete bsico de la plataforma. Pero gracias a los paquetes, todo en Symfony2 se puede ampliar o sustituir.Ese, es el tema de la siguiente parte de esta gua (Pgina 22).

    1.4 La arquitectura

    Eres mi hroe! Quin habra pensado que todava estaras aqu despus de las tres primeras partes? Tu esfuerzopronto ser bien recompensado. En las tres primeras partes no vimos en demasiada profundidad la arquitectura de laplataforma. Porque esta hace que Symfony2 est al margen de la multitud de plataformas, ahora vamos a profundizaren la arquitectura.

    1.4.1 Comprendiendo la estructura de directorios

    La estructura de directorios de una aplicacin Symfony2 es bastante flexible, pero la estructura de directorios de ladistribucin de la edicin estndar refleja la estructura tpica y recomendada de una aplicacin Symfony2:

    app/: Configuracin de la aplicacin:

    src/: El cdigo PHP del proyecto;

    vendor/: Las dependencias de terceros;

    web/: El directorio raz del servidor web.

    El Directorio web/

    El directorio web raz, es el hogar de todos los archivos pblicos y estticos tales como imgenes, hojas de estilo yarchivos JavaScript. Tambin es el lugar donde vive cada controlador frontal:

    // web/app.phprequire_once __DIR__./../app/bootstrap.php.cache;require_once __DIR__./../app/AppKernel.php;

    use Symfony\Component\HttpFoundation\Request;

    $kernel = new AppKernel(prod, false);$kernel->loadClassCache();$kernel->handle(Request::createFromGlobals())->send();

    El ncleo requiere en primer lugar el archivo bootstrap.php.cache, el cual arranca la plataforma y registra elcargador automtico (ve ms abajo).

    Al igual que cualquier controlador frontal, app.php utiliza una clase del ncleo, AppKernel, para arrancar laaplicacin.

    El directorio app/

    La clase AppKernel es el punto de entrada principal para la configuracin de la aplicacin y, como tal, se almacenaen el directorio app/.

    Esta clase debe implementar dos mtodos:

    22 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    registerBundles() debe devolver una matriz de todos los paquetes necesarios para ejecutar la aplicacin;

    registerContainerConfiguration() carga la configuracin de la aplicacin (ms sobre esto msadelante).

    La carga automtica de clases PHP se puede configurar a travs de app/autoload.php:

    // app/autoload.phpuse Symfony\Component\ClassLoader\UniversalClassLoader;

    $loader = new UniversalClassLoader();$loader->registerNamespaces(array(

    Symfony => array(__DIR__./../vendor/symfony/symfony/src, __DIR__./../vendor/bundles),Sensio => __DIR__./../vendor/bundles,JMS => __DIR__./../vendor/jms/,Doctrine\\Common => __DIR__./../vendor/doctrine/common/lib,Doctrine\\DBAL => __DIR__./../vendor/doctrine/dbal/lib,Doctrine => __DIR__./../vendor/doctrine/orm/lib,Monolog => __DIR__./../vendor/monolog/monolog/src,Assetic => __DIR__./../vendor/kriswallsmith/assetic/src,Metadata => __DIR__./../vendor/jms/metadata/src,

    ));$loader->registerPrefixes(array(

    Twig_Extensions_ => __DIR__./../vendor/twig/extensions/lib,Twig_ => __DIR__./../vendor/twig/twig/lib,

    ));

    // ...

    $loader->registerNamespaceFallbacks(array(__DIR__./../src,

    ));$loader->register();

    El Symfony\Component\ClassLoader\UniversalClassLoader se usa para cargar automticamente ar-chivos que respetan tanto los estndares de interoperabilidad tcnica de los espacios de nombres de PHP 5.3 como laconvencin de nomenclatura de las clases PEAR. Como puedes ver aqu, todas las dependencias se guardan bajo eldirectorio vendor/, pero esto es slo una convencin. Las puedes guardar donde quieras, a nivel global en el servidoro localmente en tus proyectos.

    Nota: Si deseas obtener ms informacin sobre la flexibilidad del autocargador de Symfony2, lee el captulo Elcomponente ClassLoader (Pgina 505).

    1.4.2 Comprendiendo el sistema de paquetes

    Esta seccin introduce una de las ms importantes y poderosas caractersticas de Symfony2, el sistema de paquetes.

    Un paquete es un poco como un complemento en otros programas. As que por qu se llama paquete y no comple-mento? Esto se debe a que en Symfony2 todo es un paquete, desde las caractersticas del ncleo de la plataforma hastael cdigo que escribes para tu aplicacin. Los paquetes son ciudadanos de primera clase en Symfony2. Esto te propor-ciona la flexibilidad para utilizar las caractersticas preconstruidas envasadas en paquetes de terceros o para distribuirtus propios paquetes. Adems, facilita la seleccin y eleccin de las caractersticas por habilitar en tu aplicacin yoptimizarlas en la forma que desees. Y al final del da, el cdigo de tu aplicacin es tan importante como el mismoncleo de la plataforma.

    1.4. La arquitectura 23

  • Symfony2-es, Release 2.0.12

    Registrando un paquete

    Una aplicacin se compone de paquetes tal como est definido en el mtodo registerBundles() de la claseAppKernel. Cada paquete vive en un directorio que contiene una nica clase Paquete que lo describe:

    // app/AppKernel.phppublic function registerBundles(){

    $bundles = array(new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),new Symfony\Bundle\SecurityBundle\SecurityBundle(),new Symfony\Bundle\TwigBundle\TwigBundle(),new Symfony\Bundle\MonologBundle\MonologBundle(),new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),new Symfony\Bundle\AsseticBundle\AsseticBundle(),new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),

    );

    if (in_array($this->getEnvironment(), array(dev, test))) {$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();

    }

    return $bundles;}

    Adems de AcmeDemoBundle del cual ya hemos hablado, observa que el ncleo tambin habilita otros paquetescomo FrameworkBundle, DoctrineBundle, SwiftmailerBundle y AsseticBundle. Todos ellos sonparte del ncleo de la plataforma.

    Configurando un paquete

    Cada paquete se puede personalizar a travs de archivos de configuracin escritos en YAML, XML o PHP. chale unvistazo a la configuracin predeterminada:

    # app/config/config.ymlimports:

    - { resource: parameters.yml }- { resource: security.yml }

    framework:#esi: ~#translator: { fallback:%locale% }secret: %secret%charset: UTF-8router: { resource: "%kernel.root_dir%/config/routing.yml" }form: truecsrf_protection: truevalidation: { enable_annotations: true }templating: { engines: [twig] } #assets_version: SomeVersionSchemedefault_locale: %locale%session:

    auto_start: true

    24 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    # Configuracin de Twigtwig:

    debug: %kernel.debug%strict_variables:%kernel.debug%

    # Configuracin de Asseticassetic:

    debug: %kernel.debug%use_controller: falsebundles: [ ]# java: /usr/bin/javafilters:

    cssrewrite: ~# closure:# jar:%kernel.root_dir%/java/compiler.jar# yui_css:# jar:%kernel.root_dir%/java/yuicompressor-2.4.2.jar

    # Configuracin de Doctrinedoctrine:

    dbal:driver: %database_driver%host: %database_host%port: %database_port%dbname: %database_name%user: %database_user%password:%database_password%charset: UTF8

    orm:auto_generate_proxy_classes:%kernel.debug%auto_mapping: true

    # Configuracin de Swiftmailerswiftmailer:

    transport:%mailer_transport%host: %mailer_host%username: %mailer_user%password: %mailer_password%

    jms_security_extra:secure_controllers: truesecure_all_services: false

    Cada entrada como framework define la configuracin de un paquete especfico. Por ejemplo, frameworkconfigura el FrameworkBundle mientras que swiftmailer configura el SwiftmailerBundle.

    Cada entorno puede reemplazar la configuracin predeterminada proporcionando un archivo de configuracin espec-fico. Por ejemplo, el entorno dev carga el archivo config_dev.yml, el cual carga la configuracin principal (esdecir, config.yml) y luego la modifica agregando algunas herramientas de depuracin:

    # app/config/config_dev.ymlimports:

    - { resource: config.yml }

    framework:router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }profiler: { only_exceptions: false }

    1.4. La arquitectura 25

  • Symfony2-es, Release 2.0.12

    web_profiler:toolbar: trueintercept_redirects: false

    monolog:handlers:

    main:type: streampath: %kernel.logs_dir%/%kernel.environment%.loglevel: debug

    firephp:type: firephplevel: info

    assetic:use_controller: true

    Extendiendo un paquete

    Adems de ser una buena manera de organizar y configurar tu cdigo, un paquete puede extender otro paque-te. La herencia de paquetes te permite sustituir cualquier paquete existente con el fin de personalizar sus con-troladores, plantillas, o cualquiera de sus archivos. Aqu es donde son tiles los nombres lgicos (por ejemplo,@AcmeDemoBundle/Controller/SecuredController.php): estos abstraen en dnde se almacena real-mente el recurso.

    Nombres lgicos de archivo

    Cuando quieras hacer referencia a un archivo de un paquete, utiliza esta notacin:@NOMBRE_PAQUETE/ruta/al/archivo; Symfony2 resolver @NOMBRE_PAQUETE a la ruta real del pa-quete. Por ejemplo, la ruta lgica @AcmeDemoBundle/Controller/DemoController.php se convierte ensrc/Acme/DemoBundle/Controller/DemoController.php, ya que Symfony conoce la ubicacin delAcmeDemoBundle .

    Nombres lgicos de Controlador

    Para los controladores, necesitas hacer referencia a los nombres de mtodo usando elformato NOMBRE_PAQUETE:NOMBRE_CONTROLADOR:NOMBRE_ACCIN. Por ejemplo,AcmeDemoBundle:Welcome:index representa al mtodo indexAction de la claseAcme\DemoBundle\Controller\WelcomeController.

    Nombres lgicos de plantilla

    Para las plantillas, el nombre lgico AcmeDemoBundle:Welcome:index.html.twig se convierte en la rutadel archivo src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig. Incluso las plan-tillas son ms interesantes cuando te das cuenta que no es necesario almacenarlas en el sistema de archivos. Puedesguardarlas fcilmente en una tabla de la base de datos, por ejemplo.

    26 Captulo 1. Inicio rpido

  • Symfony2-es, Release 2.0.12

    Extendiendo paquetes

    Si sigues estas convenciones, entonces puedes utilizar herencia de paquetes (Pgina 399) para redefinir archivos,controladores o plantillas. Por ejemplo, puedes crear un paquete AcmeNuevoBundle y especificar que su pa-dre es AcmeDemoBundle. Cuando Symfony carga el controlador AcmeDemoBundle:Welcome:index, buscarprimero la clase WelcomeController en AcmeNuevoBundle y luego mirar en AcmeDemoBundle. Estosignifica que, un paquete puede anular casi cualquier parte de otro paquete!

    Entiendes ahora por qu Symfony2 es tan flexible? Comparte tus paquetes entre aplicaciones, gurdalas local o glo-balmente, t eliges.

    1.4.3 Usando vendors

    Lo ms probable es que tu aplicacin depender de bibliotecas de terceros. Estas se deberan guardar en el directoriovendor/. Este directorio ya contiene las bibliotecas Symfony2, la biblioteca SwiftMailer, el ORM de Doctrine, elsistema de plantillas Twig y algunas otras bibliotecas y paquetes de terceros.

    1.4.4 Comprendiendo la cach y los registros

    Symfony2 probablemente es una de las plataformas ms rpidas hoy da. Pero cmo puede ser tan rpida si analiza einterpreta decenas de archivos YAML y XML por cada peticin? La velocidad, en parte, se debe a su sistema de cach.La configuracin de la aplicacin slo se analiza en la primer peticin y luego se compila hasta cdigo PHP simpley se guarda en el directorio app/cache/. En el entorno de desarrollo, Symfony2 es lo suficientemente inteligentecomo para vaciar la cach cuando cambias un archivo. Pero en el entorno de produccin, es tu responsabilidad borrarla cach cuando actualizas o cambias tu cdigo o configuracin.

    Al desarrollar una aplicacin web, las cosas pueden salir mal de muchas formas. Los archivos de registro en el direc-torio app/logs/ dicen todo acerca de las peticiones y ayudan a solucionar rpidamente el problema.

    1.4.5 Usando la interfaz de lnea de ordenes

    Cada aplicacin incluye una herramienta de interfaz de lnea de ordenes (app/console) que te ayuda a mantener laaplicacin. Esta proporciona ordenes que aumentan tu productividad automatizando tediosas y repetitivas tareas.

    Ejectalo sin argumentos para obtener ms informacin sobre sus posibilidades:

    php app/console

    La opcin --help te ayuda a descubrir el uso de una orden:

    php app/console router:debug --help

    1.4.6 Consideraciones finales

    Llmame loco, pero despus de leer esta parte, debes sentirte cmodo moviendo cosas y haciendo que Symfony2trabaje por ti. Todo en Symfony2 est diseado para allanar tu camino. Por lo tanto, no dudes en renombrar y moverdirectorios como mejor te parezca.

    Y eso es todo para el inicio rpido. Desde probar hasta enviar mensajes de correo electrnico, todava tienes queaprender mucho para convertirte en gur de Symfony2. Listo para zambullirte en estos temas ahora? No busques ms ve al Libro (Pgina 33) oficial y elije cualquier tema que desees.

    Un primer vistazo (Pgina 5)

    1.4. La arquitectura 27

  • Symfony2-es, Release 2.0.12

    La vista (Pgina 13)

    El controlador (Pgina 17)

    La arquitectura (Pgina 22)

    28 Captulo 1. Inicio rpido

  • Parte II

    Libro

    29

  • Symfony2-es, Release 2.0.12

    Sumrgete en Symfony2 con las guas temticas:

    31

  • Symfony2-es, Release 2.0.12

    32

  • CAPTULO 2

    Libro

    2.1 Symfony2 y fundamentos HTTP

    Enhorabuena! Al aprender acerca de Symfony2, vas bien en tu camino para llegar a ser un ms productivo, bien enfo-cado y popular desarrollador web (en realidad, en la ltima parte, ests por tu cuenta). Symfony2 est diseado paravolver a lo bsico: las herramientas de desarrollo que te permiten desarrollar ms rpido y construir aplicaciones msrobustas, mientras que permanece fuera de tu camino. Symfony est basado en las mejores ideas de muchas tecnologas:las herramientas y conceptos que ests a punto de aprender representan el esfuerzo de miles de personas, durante mu-chos aos. En otras palabras, no ests aprendiendo Symfony, ests aprendiendo los fundamentos de la web, buenasprcticas de desarrollo, y cmo utilizar muchas nuevas y asombrosas bibliotecas PHP, dentro o independientementede Symfony2. Por lo tanto, preprate!

    Fiel a la filosofa Symfony2, este captulo comienza explicando el concepto fundamental comn para el desarrollo web:HTTP. Independientemente de tus antecedentes o lenguaje de programacin preferido, este captulo es una lecturaobligada para todo mundo.

    2.1.1 HTTP es Simple

    HTTP (HyperText Transfer Protocol para los apasionados y, en Espaol Protocolo de transferencia hipertexto) esun lenguaje de texto que permite a dos mquinas comunicarse entre s. Eso es todo! Por ejemplo, al comprobar lasltimas noticias acerca de cmica xkcd, la siguiente conversacin (aproximadamente) se lleva a cabo:

    33

  • Symfony2-es, Release 2.0.12

    Y aunque el lenguaje real utilizado es un poco ms formal, sigue siendo bastante simple. HTTP es el trmino utilizadopara describir este lenguaje simple basado en texto. Y no importa cmo desarrolles en la web, el objetivo de tu servidorsiempre es entender las peticiones de texto simple, y devolver respuestas en texto simple.

    Symfony2 est construido basado en torno a esa realidad. Ya sea que te des cuenta o no, HTTP es algo que usas todoslos das. Con Symfony2, aprenders a dominarlo.

    Paso 1: El cliente enva una peticin

    Todas las conversaciones en la web comienzan con una peticin. La peticin es un mensaje de texto creado por uncliente (por ejemplo un navegador, una aplicacin para el iPhone, etc.) en un formato especial conocido como HTTP.El cliente enva la peticin a un servidor, y luego espera la respuesta.

    Echa un vistazo a la primera parte de la interaccin (la peticin) entre un navegador y el servidor web xkcd:

    Hablando en HTTP, esta peticin HTTP en realidad se vera algo parecida a esto:

    GET / HTTP/1.1Host: xkcd.comAccept: text/htmlUser-Agent: Mozilla/5.0 (Macintosh)

    34 Captulo 2. Libro

  • Symfony2-es, Release 2.0.12

    Este sencillo mensaje comunica todo lo necesario sobre qu recursos exactamente solicita el cliente. La primera lneade una peticin HTTP es la ms importante y contiene dos cosas: la URI y el mtodo HTTP.

    La URI (por ejemplo, /, /contact, etc.) es la direccin o ubicacin que identifica unvocamente al recurso que elcliente quiere. El mtodo HTTP (por ejemplo, GET) define lo que quieres hacer con el recurso. Los mtodos HTTPson los verbos de la peticin y definen las pocas formas ms comunes en que puedes actuar sobre el recurso:

    GET Recupera el recurso desde el servidorPOST Crea un recurso en el servidorPUT Actualiza el recurso en el servidorDELETE Elimina el recurso del servidor

    Con esto en mente, te puedes imaginar que una peticin HTTP podra ser similar a eliminar una entrada de blogespecfica, por ejemplo:

    DELETE /blog/15 HTTP/1.1

    Nota: En realidad, hay nueve mtodos HTTP definidos por la especificacin HTTP, pero muchos de ellos no seutilizan o apoyan ampliamente. En realidad, muchos navegadores modernos no apoyan los mtodos PUT y DELETE.

    Adems de la primera lnea, una peticin HTTP invariablemente contiene otras lneas de informacin conocidas comocabeceras de peticin. Las cabeceras pueden suministrar una amplia gama de informacin como el servidor (o host)solicitado, los formatos de respuesta que acepta el cliente (Accept) y la aplicacin que utiliza el cliente para realizarla peticin (User-Agent). Existen muchas otras cabeceras y se pueden encontrar en el artculo Lista de campos delas cabeceras HTTP en la Wikipedia.

    Paso 2: El servidor devuelve una respuesta

    Una vez que un servidor ha recibido la peticin, sabe exactamente qu recursos necesita el cliente (a travs de la URI)y lo que el cliente quiere hacer con ese recurso (a travs del mtodo). Por ejemplo, en el caso de una peticin GET, elservidor prepara el recurso y lo devuelve en una respuesta HTTP. Considera la respuesta del servidor web, xkcd:

    Traducida a HTTP, la respuesta enviada de vuelta al navegador se ver algo similar a esto:

    HTTP/1.1 200 OKDate: Sat, 02 Apr 2011 21:05:05 GMTServer: lighttpd/1.4.19Content-Type: text/html

    2.1. Symfony2 y fundamentos HTTP 35

  • Symfony2-es, Release 2.0.12

    La respuesta HTTP contiene el recurso solicitado (contenido HTML en este caso), as como otra informacin acercade la respuesta. La primera lnea es especialmente importante y contiene el cdigo de estado HTTP (200 en este caso)de la respuesta. El cdigo de estado comunica el resultado global de la peticin devuelta al cliente. Tuvo xito lapeticin? Hubo algn error? Existen diferentes cdigos de estado que indican xito, un error o qu ms se necesitahacer con el cliente (por ejemplo, redirigirlo a otra pgina). La lista completa se puede encontrar en el artculo Listade cdigos de estado HTTP en la Wikipedia.

    Al igual que la peticin, una respuesta HTTP contiene datos adicionales conocidos como cabeceras HTTP. Por ejem-plo, una importante cabecera de la respuesta HTTP es Content-Type. El cuerpo del mismo recurso se puededevolver en varios formatos diferentes, incluyendo HTML, XML o JSON y la cabecera Content-Type utiliza In-ternet Media Types como text/html para decirle al cliente cual formato se ha devuelto. Puedes encontrar una listacompleta en el artculo Lista de medios de comunicacin de Internet en la Wikipedia.

    Existen muchas otras cabeceras, algunas de las cuales son muy poderosas. Por ejemplo, ciertas cabeceras se puedenusar para crear un poderoso sistema de memoria cach.

    Peticiones, respuestas y desarrollo Web

    Esta conversacin peticin-respuesta es el proceso fundamental que impulsa toda la comunicacin en la web. Y tanimportante y poderoso como es este proceso, inevitablemente es simple.

    El hecho ms importante es el siguiente: independientemente del lenguaje que utilices, el tipo de aplicacin queconstruyas (web, mvil, API JSON), o la filosofa de desarrollo que sigas, el objetivo final de una aplicacin siemprees entender cada peticin y crear y devolver la respuesta adecuada.

    Symfony est diseado para adaptarse a esta realidad.

    Truco: Para ms informacin acerca de la especificacin HTTP, lee la referencia original HTTP 1.1 RFC o HTTPBis, el cual es un esfuerzo activo para aclarar la especificacin original. Una gran herramienta para comprobar tantola peticin como las cabeceras de la respuesta mientras navegas es la extensin Cabeceras HTTP en vivo (Live HTTPHeaders) para Firefox.

    2.1.2 Peticiones y respuestas en PHP

    Entonces cmo interactas con la peticin y creas una respuesta utilizando PHP? En realidad, PHP te abstrae unpoco de todo el proceso:

  • Symfony2-es, Release 2.0.12

    de la respuesta y simplemente imprimir el contenido real que ser la porcin que contiene el mensaje de la respuesta.PHP crear una verdadera respuesta HTTP y la devolver al cliente:

    HTTP/1.1 200 OKDate: Sat, 03 Apr 2011 02:14:33 GMTServer: Apache/2.2.17 (Unix)Content-Type: text/html

    La URI solicitada es: /testing?foo=symfonyEl valor del parmetro "foo" es: symfony

    2.1.3 Peticiones y respuestas en Symfony

    Symfony ofrece una alternativa al enfoque de PHP a travs de dos clases que te permiten interactuar con la peticinHTTP y la respuesta de una manera ms fcil. La clase Symfony\Component\HttpFoundation\Request esuna sencilla representacin orientada a objetos del mensaje de la peticin HTTP. Con ella, tienes toda la informacina tu alcance:

    use Symfony\Component\HttpFoundation\Request;

    $request = Request::createFromGlobals();

    // la URI solicitada (p.e. /sobre) menos algunos parmetros de la consulta$request->getPathInfo();

    // recupera las variables GET y POST respectivamente$request->query->get(foo);$request->request->get(bar, default value if bar does not exist);

    // recupera las variables de SERVER$request->server->get(HTTP_HOST);

    // recupera una instancia del archivo subido identificado por foo$request->files->get(foo);

    // recupera un valor de COOKIE$request->cookies->get(PHPSESSID);

    // recupera una cabecera HTTP de la peticin, normalizada, con ndices en minscula$request->headers->get(host);$request->headers->get(content_type);

    $request->getMethod(); // GET, POST, PUT, DELETE, HEAD$request->getLanguages(); // un arreglo de idiomas aceptados por el cliente

    Como bono adicional, en el fondo la clase Peticin hace un montn de trabajo del cual nunca tendrs que preo-cuparte. Por ejemplo, el mtodo isSecure() comprueba tres diferentes valores en PHP que pueden indicar si elusuario est conectado a travs de una conexin segura (es decir, https).

    2.1. Symfony2 y fundamentos HTTP 37

  • Symfony2-es, Release 2.0.12

    ParameterBags y atributos de la peticin

    Como vimos anteriormente, las variables $_GET y $_POST son accesibles a travs de laspropiedades query y request, respectivamente. Cada uno de estos objetos es un ob-jeto de la Symfony\Component\HttpFoundation\ParameterBag, la cual cuen-ta con mtodos cmo: :method:Symfony\\Component\\HttpFoundation\\ParameterBag::get,:method:Symfony\\Component\\HttpFoundation\\ParameterBag::has, :met-hod:Symfony\\Component\\HttpFoundation\\ParameterBag::all entre otros. De hecho, todas las pro-piedades pblicas utilizadas en el ejemplo anterior son un ejemplo del ParameterBag. La clase Peticintambin tiene una propiedad pblica attributes, que tiene datos especiales relacionados en cmo funcionainternamente la aplicacin. Para la plataforma Symfony2, attibutes mantiene los valores devueltos por laruta buscada, tal como _controller, id (por lo tanto si tienes un comodn {id}), e incluso el nombre dela ruta buscada (_route). La propiedad attributes existe enteramente para ser un lugar donde se puedapreparar y almacenar informacin del contexto especfico de la peticin.

    Symfony tambin proporciona una clase Respuesta: una simple representacin PHP de un mensaje de respuestaHTTP. Esto permite que tu aplicacin utilice una interfaz orientada a objetos para construir la respuesta que serdevuelta al cliente:

    use Symfony\Component\HttpFoundation\Response;$response = new Response();

    $response->setContent(Hello world!);$response->setStatusCode(200);$response->headers->set(Content-Type, text/html);

    // imprime las cabeceras HTTP seguidas por el contenido$response->send();

    Si Symfony no ofreciera nada ms, ya tendras un conjunto de herramientas para acceder fcilmente a la informacinde la peticin y una interfaz orientada a objetos para crear la respuesta. Incluso, a medida que aprendas muchas delas poderosas caractersticas de Symfony, nunca olvides que el objetivo de tu aplicacin es interpretar una peticin ycrear la respuesta adecuada basada en la lgica de tu aplicacin.

    Truco: Las clases Respuesta y Peticin forman parte de un componente independiente incluido en Symfonyllamado HttpFoundation. Este componente se puede utilizar completamente independiente de Symfony y tambinproporciona clases para manejar sesiones y subir archivos.

    2.1.4 El viaje desde la peticin hasta la respuesta

    Al igual que el mismo HTTP, los objetos Peticin y Respuesta son bastante simples. La parte difcil de laconstruccin de una aplicacin es escribir lo que viene en el medio. En otras palabras, el verdadero trabajo viene alescribir el cdigo que interpreta la informacin de la peticin y crea la respuesta.

    Tu aplicacin probablemente hace muchas cosas, como enviar correo electrnico, manejar los formularios presentados,guardar cosas en una base de datos, reproducir las pginas HTML y proteger el contenido con seguridad. Cmo puedesmanejar todo esto y todava mantener tu cdigo organizado y fcil de mantener?

    Symfony fue creado para resolver estos problemas para que no tengas que hacerlo personalmente.

    38 Captulo 2. Libro

  • Symfony2-es, Release 2.0.12

    El controlador frontal

    Tradicionalmente, las aplicaciones eran construidas de modo que cada pgina de un sitio tena su propio archivofsico:

    index.phpcontacto.phpblog.php

    Hay varios problemas con este enfoque, incluyendo la falta de flexibilidad de las URL (qu pasa si quieres cambiarblog.php a noticias.php sin romper todos tus enlaces?) y el hecho de que cada archivo debe incluir manual-mente un conjunto de archivos bsicos para la seguridad, conexiones a base de datos y que el aspecto del sitio puedapermanecer constante.

    Una mucho mejor solucin es usar un controlador frontal: un solo archivo PHP que se encargue de todas las peticionesque llegan a tu aplicacin. Por ejemplo:

    /index.php ejecuta index.php/index.php/contact ejecuta index.php/index.php/blog ejecuta index.php

    Truco: Usando mod_rewrite de Apache (o equivalente con otros servidores web), las URL se pueden limpiarfcilmente hasta ser slo /, /contact y /blog.

    Ahora, cada peticin se maneja exactamente igual. En lugar de URL individuales ejecutando diferentes archivos PHP,el controlador frontal siempre se ejecuta, y el enrutado de diferentes URL a diferentes partes de tu aplicacin se realizainternamente. Esto resuelve los problemas del enfoque original. Casi todas las aplicaciones web modernas lo hacenincluyendo aplicaciones como WordPress.

    Mantente organizado

    Pero dentro de tu controlador frontal, cmo sabes qu pgina debes reproducir y cmo puedes reproducir cada unaen forma sana? De una forma u otra, tendrs que comprobar la URI entrante y ejecutar diferentes partes de tu cdigoen funcin de ese valor. Esto se puede poner feo rpidamente:

    // index.php

    $request = Request::createFromGlobals();$path = $request->getPathInfo(); // La ruta URI solicitada

    if (in_array($path, array(, /)) {$response = new Response(Welcome to the homepage.);

    } elseif ($path == /contact) {$response = new Response(Contact us);

    } else {$response = new Response(Page not found., 404);

    }$response->send();

    La solucin a este problema puede ser difcil. Afortunadamente esto es exactamente para lo que Symfony est diseado.

    El flujo de las aplicaciones Symfony

    Cuando dejas que Symfony controle cada peticin, la vida es mucho ms fcil. Symfony sigue el mismo patrn simpleen cada peticin:

    2.1. Symfony2 y fundamentos HTTP 39

  • Symfony2-es, Release 2.0.12

    Figura 2.1: Las peticiones entrantes son interpretadas por el enrutador y pasadas a las funciones controladoras queregresan objetos Respuesta.

    Cada pgina de tu sitio est definida en un archivo de configuracin de enrutado que asigna las diferentes URL adiferentes funciones PHP. El trabajo de cada funcin PHP conocida como controlador, es utilizar la informacin de lapeticin junto con muchas otras herramientas que Symfony pone a tu disposicin para crear y devolver un objetoRespuesta. En otras palabras, el controlador es donde est tu cdigo: ah es dnde se interpreta la peticin y creauna respuesta.

    As de fcil! Repasemos:

    Cada peticin ejecuta un archivo controlador frontal;

    El sistema de enrutado determina cual funcin PHP se debe ejecutar en base a la informacin de la peticin y laconfiguracin de enrutado que hemos creado;

    La funcin PHP correcta se ejecuta, donde tu cdigo crea y devuelve el objeto Respuesta adecuado.

    Una peticin Symfony en accin

    Sin bucear demasiado en los detalles, veamos este proceso en accin. Supongamos que deseas agregar una pgina/contact a tu aplicacin Symfony. En primer lugar, empezamos agregando una entrada /contact a tu archivo deconfiguracin de enrutado:

    contact:pattern: /contactdefaults: { _controller: AcmeDemoBundle:Main:contact }

    Nota: En este ejemplo utilizamos YAML (Pgina 563) para definir la configuracin de enrutado. La configuracin deenrutado tambin se puede escribir en otros formatos, tal como XML o PHP.

    Cuando alguien visita la pgina /contact, esta ruta coincide, y se ejecuta el controlador especificado. Como veremosen el captulo Enrutando (Pgina 81), La cadena AcmeDemoBundle:Main:contact es una sintaxis corta queapunta hacia el mtodo PHP contactAction dentro de una clase llamada MainController:

    class MainController{

    public function contactAction()

    40 Captulo 2. Libro

  • Symfony2-es, Release 2.0.12

    {return new Response(Contact us!);

    }}

    En este ejemplo muy simple, el controlador simplemente crea un objeto Respuesta con el cdigo HTML"Contact us!". En el captulo Controlador (Pgina 71), aprenders cmo un controlador puedereproducir plantillas, permitiendo que tu cdigo de presentacin (es decir, algo que en realidad escribe HTML) vivaen un archivo de plantilla separado. Esto libera al controlador de preocuparse slo de las cosas difciles: la interaccincon la base de datos, la manipulacin de los datos presentados o el envo de mensajes de correo electrnico.

    2.1.5 Symfony2: Construye tu aplicacin, no tus herramientas.

    Ahora sabemos que el objetivo de cualquier aplicacin es interpretar cada peticin entrante y crear una respuestaadecuada. Cuando una aplicacin crece, es ms difcil mantener organizado tu cdigo y que a la vez sea fcil darlemantenimiento. Invariablemente, las mismas tareas complejas siguen viniendo una y otra vez: la persistencia de cosasa la base de datos, procesamiento y reutilizacin de plantillas, manejo de formularios presentados, envo de mensajesde correo electrnico, validacin de entradas del usuario y administracin de la seguridad.

    La buena nueva es que ninguno de estos problemas es nico. Symfony proporciona una plataforma completa, conherramientas que te permiten construir tu aplicacin, no tus herramientas. Con Symfony2, nada se te impone: eres librede usar la plataforma Symfony completa, o simplemente una pieza de Symfony por s misma.

    Herramientas independientes: Componentes de Symfony2

    Entonces, qu es Symfony2? En primer lugar, Symfony2 es una coleccin de ms de veinte bibliotecas independientesque se pueden utilizar dentro de cualquier proyecto PHP. Estas bibliotecas, llamadas componentes de Symfony2,contienen algo til para casi cualquier situacin, independientemente de cmo desarrolles tu proyecto. Para nombraralgunas:

    HttpFoundation Contiene las clases Peticin y Respuesta, as como otras clases para manejar sesionesy cargar archivos;

    Routing Potente y rpido sistema de enrutado que te permite asignar una URI especfica (por ejemplo/contacto) a cierta informacin acerca de cmo se debe manejar dicha peticin (por ejemplo, ejecutar elmtodo contactoAction());

    Form Una completa y flexible plataforma para crear formularios y procesar los datos presentados en ellos;

    Validator Un sistema para crear reglas sobre datos y entonces, cuando el usuario presenta los datos comprobarsi son vlidos o no siguiendo esas reglas;

    ClassLoader Una biblioteca para carga automtica que te permite utilizar clases PHP sin necesidad derequerir manualmente los archivos que contienen esas clases;

    Templating Un juego de herramientas para reproducir plantillas, la cual gestiona la herencia de plantillas (esdecir, una plantilla est decorada con un diseo) y realiza otras tareas de plantilla comunes;

    Security Una poderosa biblioteca para manejar todo tipo de seguridad dentro de una aplicacin;

    Translation Una plataforma para traducir cadenas en tu aplicacin.

    Todos y cada uno de estos componentes se desacoplan y se pueden utilizar en cualquier proyecto PHP, independiente-mente de si utilizas la plataforma Symfony2. Cada parte est hecha para utilizarla si es conveniente y sustituirse cuandosea necesario.

    2.1. Symfony2 y fundamentos HTTP 41

  • Symfony2-es, Release 2.0.12

    La solucin completa: La plataforma Symfony2

    Entonces, qu es la plataforma Symfony2? La plataforma Symfony2 es una biblioteca PHP que realiza dos distintastareas:

    1. Proporciona una seleccin de componentes (es decir, los componentes Symfony2) y bibliotecas de terceros (porejemplo, SwiftMailer para enviar mensajes de correo electrnico);

    2. Proporciona configuracin sensible y un pegamento que une la biblioteca con todas estas piezas.

    El objetivo de la plataforma es integrar muchas herramientas independientes con el fin de proporcionar una experienciacoherente al desarrollador. Incluso la propia plataforma es un paquete Symfony2 (es decir, un complemento) que sepuede configurar o sustituir completamente.

    Symfony2 proporciona un potente conjunto de herramientas para desarrollar aplicaciones web rpidamente sin impo-nerse en tu aplicacin. Los usuarios normales rpidamente pueden comenzar el desarrollo usando una distribucinSymfony2, que proporciona un esqueleto del proyecto con parmetros predeterminados. Para los usuarios ms avanza-dos, el cielo es el lmite.

    2.2 Symfony2 frente a PHP simple

    Por qu Symfony2 es mejor que slo abrir un archivo y escribir PHP simple?

    Si nunca has usado una plataforma PHP, no ests familiarizado con la filosofa MVC, o simplemente te preguntasqu es todo ese alboroto en torno a Symfony2, este captulo es para ti. En vez de decirte que Symfony2 te permitedesarrollar software ms rpido y mejor que con PHP simple, debes verlo t mismo.

    En este captulo, vamos a escribir una aplicacin sencilla en PHP simple, y luego la reconstruiremos para que estmejor organizada. Podrs viajar a travs del tiempo, viendo las decisiones de por qu el desarrollo web ha evolucionadoen los ltimos aos hasta donde est ahora.

    Al final, vers cmo Symfony2 te puede rescatar de las tareas cotidianas y te permite recuperar el control de tu cdigo.

    2.2.1 Un sencillo blog en PHP simple

    En este captulo, crearemos una simblica aplicacin de blog utilizando slo PHP simple. Para empezar, crea unapgina que muestre las entradas del blog que se han persistido en la base de datos. Escribirla en PHP simple es rpidoy sucio:

    List of Posts

    List of Posts

    42 Captulo 2. Libro

  • Symfony2-es, Release 2.0.12

  • Symfony2-es, Release 2.0.12

    List of Posts

    List of Posts

  • Symfony2-es, Release 2.0.12

    }close_database_connection($link);

    return $posts;}

    Truco: Utilizamos el nombre de archivo model.php debido a que el acceso a la lgica y los datos de una aplicacin,tradicionalmente, se conoce como la capa del modelo. En una aplicacin bien organizada, la mayora del cdigo querepresenta tu lgica de negocio debe vivir en el modelo (en lugar de vivir en un controlador). Y, a diferencia de esteejemplo, slo una parte (o ninguna) del modelo realmente est interesada en acceder a la base de datos.

    El controlador (index.php) ahora es muy sencillo:

    La plantilla (templates/list.php) ahora se puede simplificar para extender el diseo:

    List of Posts

  • Symfony2-es, Release 2.0.12

    Ahora hemos introducido una metodologa que nos permite reutilizar el diseo. Desafortunadamente, para lograrlo,estamos obligados a utilizar algunas desagradables funciones de PHP (ob_start(), ob_get_clean()) en laplantilla. Symfony2 utiliza un componente Templating que nos permite realizar esto limpia y fcilmente. En brevelo vers en accin.

    2.2.2 Agregando una pgina "show" al blog

    La pgina "list" del blog se ha rediseado para que el cdigo est mejor organizado y sea reutilizable. Para probarlo,aade una pgina "show" al blog, que muestre una entrada individual del blog identificada por un parmetro deconsulta id.

    Para empezar, crea una nueva funcin en el archivo model.php que recupere un resultado individual del blog basn-dose en un identificador dado:

    // model.phpfunction get_post_by_id($id){

    $link = open_database_connection();

    $id = mysql_real_escape_string($id);$query = SELECT date, title, body FROM post WHERE id = .$id;$result = mysql_query($query);$row = mysql_fetch_assoc($result);

    close_database_connection($link);

    return $row;}

    A continuacin, crea un nuevo archivo llamado show.php el controlador para esta nueva pgina:

    46 Captulo 2. Libro

  • Symfony2-es, Release 2.0.12

    Ahora, es muy fcil crear la segunda pgina y sin duplicar cdigo. Sin embargo, esta pgina introduce problemasan ms perniciosos que una plataforma puede resolver por ti. Por ejemplo, un parmetro id ilegal u omitido enla consulta har que la pgina se bloquee. Sera mejor si esto reprodujera una pgina 404, pero sin embargo, enrealidad esto no se puede hacer fcilmente. Peor an, si olvidaras desinfectar el parmetro id por medio de la funcinmysql_real_escape_string(), tu base de datos estara en riesgo de un ataque de inyeccin SQL.

    Otro importante problema es que cada archivo de controlador individual debe incluir al archivo model.php. Qupasara si cada archivo de controlador de repente tuviera que incluir un archivo adicional o realizar alguna tarea global(por ejemplo, reforzar la seguridad)? Tal como est ahora, el cdigo tendra que incluir todos los archivos de loscontroladores. Si olvidas incluir algo en un solo archivo, esperemos que no sea alguno relacionado con la seguridad...

    2.2.3 El controlador frontal al rescate

    Una mucho mejor solucin es usar un controlador frontal: un nico archivo PHP a travs del cual se procesen todaslas peticiones. Con un controlador frontal, la URI de la aplicacin cambia un poco, pero se vuelve ms flexible:

    Sin controlador frontal/index.php => (ejecuta index.php) la pgina lista de mensajes./show.php => (ejecuta show.php) la pgina muestra un mensaje particular.

    Con index.php como controlador frontal/index.php => (ejecuta index.php) la pgina lista de mensajes./index.php/show => (ejecuta index.php) la pgina muestra un mensaje particular.

    Truco: Puedes quitar la porcin index.php de la URI si utilizas las reglas de reescritura de Apache (o equivalentes).En ese caso, la URI resultante de la pgina show del blog simplemente sera /show.

    Cuando se usa un controlador frontal, un solo archivo PHP (index.php en este caso) procesa todas las peticiones.Para la pgina show del blog, /index.php/show realmente ejecuta el archivo index.php, que ahora es elresponsable de dirigir internamente las peticiones basndose en la URI completa. Como puedes ver, un controladorfrontal es una herramienta muy poderosa.

    Creando el controlador frontal

    Ests a punto de dar un gran paso en la aplicacin. Con un archivo manejando todas las peticiones, puedes centralizarcosas tales como el manejo de la seguridad, la carga de configuracin y enrutado. En esta aplicacin, index.phpahora debe ser lo suficientemente inteligente como para reproducir la lista de entradas del blog o mostrar la pgina deuna entrada particular basndose en la URI solicitada:

  • Symfony2-es, Release 2.0.12

    echo Page Not Found;}

    Por organizacin, ambos controladores (antes index.php y show.php) son funciones PHP y cada una se hamovido a un archivo separado, controllers.php:

    function list_action(){

    $posts = get_all_posts();require templates/list.php;

    }

    function show_action($id){

    $post = get_post_by_id($id);require templates/show.php;

    }

    Como controlador frontal, index.php ha asumido un papel completamente nuevo, el cual incluye la carga delas bibliotecas del ncleo y encaminar la aplicacin para invocar a uno de los dos controladores (las funcioneslist_action() y show_action()). En realidad, el controlador frontal est empezando a verse y actuar co-mo el mecanismo Symfony2 para la manipulacin y enrutado de peticiones.

    Truco: Otra ventaja del controlador frontal es la flexibilidad de las URL. Ten en cuenta que la URL a la pgina showdel blog se puede cambiar de /show a /read cambiando el cdigo solamente en una nica ubicacin. Antes, eranecesario cambiar todo un archivo para cambiar el nombre. En Symfony2, incluso las URL son ms flexibles.

    Por ahora, la aplicacin ha evolucionado de un nico archivo PHP, a una estructura organizada y permite la reutiliza-cin de cdigo. Debes estar feliz, pero an lejos de estar satisfecho. Por ejemplo, el sistema de enrutado es voluble,y no reconoce que la pgina list (/index.php) tambin debe ser accesible a travs de / (si has agregado lasreglas de reescritura de Apache). Adems, en lugar de desarrollar el blog, una gran cantidad del tiempo se ha gastadotrabajando en la arquitectura del cdigo (por ejemplo, el enrutado, invocando controladores, plantillas, etc.) Se ten-dr que gastar ms tiempo para manejar la presentacin de formularios, validacin de entradas, registro de sucesos yseguridad. Por qu tienes que reinventar soluciones a todos estos problemas rutinarios?

    Aadiendo un toque Symfony2

    Symfony2 al rescate. Antes de utilizar Symfony2 realmente, debes asegurarte de que PHP sabe cmo encontrar lasclases Symfony2. Esto se logra a travs de un cargador automtico que proporciona Symfony. Un cargador automticoes una herramienta que permite empezar a utilizar clases PHP sin incluir explcitamente el archivo que contiene laclase.

    Primero, descarga Symfony y colcalo en el directorio vendor/symfony/symfony/. A continuacin, crea unarchivo app/bootstrap.php. Se usa para requerir los dos archivos en la aplicacin y para configurar elcargador automtico:

  • Symfony2-es, Release 2.0.12

    ));

    $loader->register();

    Esto le dice al cargador automtico dnde estn las clases de Symfony. Con esto, puedes comenzar a utilizar las clasesde Symfony sin necesidad de utilizar la declaracin require en los archivos que las utilizan.

    La esencia de la filosofa Symfony es la idea de que el trabajo principal de unaaplicacin es interpretar cada peticin y devolver una respuesta. Con este fin, Sym-fony2 proporciona ambas clases Symfony\Component\HttpFoundation\Request ySymfony\Component\HttpFoundation\Response. Estas clases son representaciones orientadas aobjetos de la peticin HTTP que se est procesando y la respuesta HTTP que devolver. salas para mejorar el blog:

  • Symfony2-es, Release 2.0.12

    {extract($args);ob_start();require $path;$html = ob_get_clean();

    return $html;}

    Al reunir una pequea parte de Symfony2, la aplicacin es ms flexible y fiable. La Peticin proporciona unamanera confiable para acceder a informacin de la peticin HTTP. Especialmente, el mtodo getPathInfo()devuelve una URI limpia (siempre devolviendo /show y nunca /index.php/show). Por lo tanto, incluso si elusuario va a /index.php/show, la aplicacin es lo suficientemente inteligente para encaminar la peticin haciashow_action().

    El objeto Respuesta proporciona flexibilidad al construir la respuesta HTTP, permitiendo que las cabeceras HTTPy el contenido se agreguen a travs de una interfaz orientada a objetos. Y aunque las respuestas en esta aplicacin son