symfony2-es.pdf - Documentsdocumentslide.com › DocumentsManual de Symfony2 Release 2.0.1...

download symfony2-es.pdf - Documentsdocumentslide.com › DocumentsManual de Symfony2 Release 2.0.1 Traducido por Nacho Pacheco August 29, 2011 à ndice general I GuÃa de inicio rápido

If you can't read please download the document

Transcript of symfony2-es.pdf - Documentsdocumentslide.com › DocumentsManual de Symfony2 Release 2.0.1...

symfony2-es.pdf - [PDF Document]

Sign in Register

Hide

symfony2-es.pdf

Category: Documents

DownloadReport copyright

Share:

Copy

Description

Manual de Symfony2 Release 2.0.1 Traducido por Nacho Pacheco August 29, 2011 ndice general I Gua de inicio rpido 1 1. Gua de inicio rpido 5 1.1. Un primer

Related documents

symfony2-es.pdf

View more

About us|Terms

out of

symfony2-es.pdf

Convert error! Download to viewManual de Symfony2Release 2.0.1

Traducido por Nacho Pacheco

August 29, 2011

ndice general

I Gua de inicio rpido 1

1. Gua de 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412.3. Instalando y configurando Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532.4. Creando pginas en Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572.5. Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712.6. Enrutando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812.7. Configuracin bsica de rutas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 842.8. Enrutando con marcadores de posicin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 852.9. Marcadores de posicin obligatorios y opcionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 862.10. Agregando requisitos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 882.11. Agregando requisitos de mtodo HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 902.12. Ejemplo de enrutado avanzado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 922.13. Parmetros de enrutado especiales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 932.14. Prefijando rutas importadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962.15. Generando URL absolutas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 972.16. Generando URL con cadena de consulta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 972.17. Generando URL desde una plantilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982.18. Creando y usando plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982.19. Bases de datos y Doctrine (El modelo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1152.20. Probando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1372.21. Validando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1492.22. Formularios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1602.23. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

I

2.24. Cach HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2102.25. Traduciendo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2242.26. Contenedor de servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2372.27. Rendimiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2522.28. Funcionamiento interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2542.29. API estable de Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

III Recetario 273

3. Recetario 2753.1. Cmo crear y guardar un proyecto Symfony2 en git . . . . . . . . . . . . . . . . . . . . . . . . . . . 2753.2. Cmo personalizar pginas de error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773.3. Cmo definir controladores como servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2783.4. Cmo forzar las rutas para utilizar siempre HTTPS . . . . . . . . . . . . . . . . . . . . . . . . . . . 2793.5. Cmo permitir un carcter / en un parmetro de ruta . . . . . . . . . . . . . . . . . . . . . . . . . 2803.6. Cmo utilizar Assetic para gestionar activos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2813.7. Cmo minimizar JavaScript y hojas de estilo con YUI Compressor . . . . . . . . . . . . . . . . . . 2853.8. Cmo utilizar Assetic para optimizar imgenes con funciones Twig . . . . . . . . . . . . . . . . . 2873.9. Cmo aplicar un filtro Assetic a una extensin de archivo especifica . . . . . . . . . . . . . . . . 2913.10. Cmo manejar archivos subidos con Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2943.11. Extensiones Doctrine: Timestampable: Sluggable, Translatable, etc. . . . . . . . . . . . 3003.12. Registrando escuchas y suscriptores de eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3003.13. Cmo generar entidades de una base de datos existente . . . . . . . . . . . . . . . . . . . . . . . . . 3023.14. Cmo utiliza Doctrine la capa DBAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3043.15. Cmo trabajar con varios gestores de entidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3073.16. Registrando funciones DQL personalizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3083.17. Cmo personalizar la reproduccin de un formulario . . . . . . . . . . . . . . . . . . . . . . . . . . 3093.18. Cmo crear un tipo de campo de formulario personalizado . . . . . . . . . . . . . . . . . . . . . . . 3223.19. Cmo crear una restriccin de validacin personalizada . . . . . . . . . . . . . . . . . . . . . . . . 3233.20. Cmo dominar y crear nuevos entornos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3243.21. Cmo configurar parmetros externos en el contenedor de servicios . . . . . . . . . . . . . . . . . . 3293.22. Cmo utilizar el patrn fbrica para crear servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . 3313.23. Cmo gestionar dependencias comunes con servicios padre . . . . . . . . . . . . . . . . . . . . . . 3353.24. Cmo utilizar PdoSessionStorage para almacenar sesiones en la base de datos . . . . . . . . . . . . . 3443.25. Estructura de un paquete y buenas prcticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3463.26. Cmo utilizar la herencia de paquetes para redefinir partes de un paquete . . . . . . . . . . . . . . . 3503.27. Cmo exponer la configuracin semntica de un paquete . . . . . . . . . . . . . . . . . . . . . . . . 3503.28. Cmo enviar correo electrnico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3583.29. Cmo utilizar Gmail para enviar mensajes de correo electrnico . . . . . . . . . . . . . . . . . . . . 3613.30. Cmo trabajar con correos electrnicos durante el desarrollo . . . . . . . . . . . . . . . . . . . . . . 3613.31. Cmo organizar el envo de correo electrnico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3633.32. Cmo simular autenticacin HTTP en una prueba funcional . . . . . . . . . . . . . . . . . . . . . . 3653.33. Cmo probar la interaccin de varios clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3653.34. Cmo utilizar el generador de perfiles en una prueba funcional . . . . . . . . . . . . . . . . . . . . . 3663.35. Cmo probar repositorios Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3673.36. Cmo agregar la funcionalidad recurdame al inicio de sesin . . . . . . . . . . . . . . . . . . . . 3703.37. Cmo implementar tu propio votante para agregar direcciones IP a la lista negra . . . . . . . . . . . 3733.38. Listas de control de acceso (ACL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3763.39. Conceptos ACL avanzados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3793.40. Cmo forzar HTTPS o HTTP a diferentes URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3823.41. Cmo personalizar el formulario de acceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3833.42. Cmo proteger cualquier servicio o mtodo de tu aplicacin . . . . . . . . . . . . . . . . . . . . . . 3893.43. Cmo cargar usuarios de la base de datos con seguridad (la entidad Proveedor) . . . . . . . . . . . . 393

II

3.44. Cmo crear un proveedor de usuario personalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . 3933.45. Cmo crear un proveedor de autenticacin personalizado . . . . . . . . . . . . . . . . . . . . . . . . 3943.46. Cmo utilizar Varnish para acelerar mi sitio web . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4023.47. Cmo usar plantillas PHP en lugar de Twig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4033.48. Cmo cargar clases automticamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4073.49. Cmo localizar archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4093.50. Cmo crear la consola/lnea de ordenes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4123.51. Cmo optimizar tu entorno de desarrollo para depuracin . . . . . . . . . . . . . . . . . . . . . . . 4163.52. Cmo utilizar Monolog para escribir Registros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4173.53. Cmo extender una clase sin necesidad de utilizar herencia . . . . . . . . . . . . . . . . . . . . . . . 4213.54. Cmo personalizar el comportamiento de un mtodo sin utilizar herencia . . . . . . . . . . . . . . . 4233.55. Cmo registrar un nuevo formato de peticin y tipo MIME . . . . . . . . . . . . . . . . . . . . . . . 4243.56. Cmo crear un colector de datos personalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4253.57. Cmo crear un servicio Web SOAP en un controlador de Symfony2 . . . . . . . . . . . . . . . . . . 4283.58. En qu difiere Symfony2 de symfony1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

IV Documentos de referencia 439

4. Documentos de referencia 4434.1. Configurando el FrameworkBundle (framework) . . . . . . . . . . . . . . . . . . . . . . . . . 4434.2. Referencia de configuracin de AsseticBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . 4464.3. Referencia de configuracin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4474.4. Referencia en configurando Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4524.5. Configurando SwiftmailerBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4554.6. Referencia de configuracin de TwigBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4554.7. Referencia de configuracin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4574.8. Configurando WebProfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4584.9. Referencia de tipos para formulario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4594.10. Referencia de funciones de formulario en plantillas Twig . . . . . . . . . . . . . . . . . . . . . . . . 5134.11. Referencia de restricciones de validacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5144.12. Etiquetas de inyeccin de dependencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5604.13. YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5654.14. Requisitos para que funcione Symfony2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570

V Paquetes 573

5. Paquetes SE de Symfony 5775.1. SensioFrameworkExtraBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5775.2. SensioGeneratorBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5855.3. Descripcin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5885.4. DoctrineFixturesBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5925.5. DoctrineMigrationsBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5975.6. DoctrineMongoDBBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601

VI Colaborando 621

6. Colaborando 6256.1. Aportando cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6256.2. Aportando documentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6336.3. Aportando cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648

III

IV

Parte I

Gua de inicio rpido

1

Manual de Symfony2, Release 2.0.1

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

3

Manual de Symfony2, Release 2.0.1

4

CAPTULO 1

Gua de 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 simple proyecto en accin.

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/ Manual de Symfony2, Release 2.0.1

...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:

php bin/vendors 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 felicitarte por tu arduo trabajo hasta el momento!

6 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

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 el cdigo de 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 41).

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/hola/Nacho

1.1. Un primer vistazo 7

Manual de Symfony2, Release 2.0.1

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/hola/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/hola/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 - el archivo de configuracin app/config/routing_dev.yml tambin es cargado. En laedicin estndar, las rutas a estas pginas de demostracin se encuentran en ese archivo:

# app/config/routing_dev.yml_bienvenida:

pattern: /defaults: { _controller: AcmeDemoBundle:Bienvenida: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 solicite, el controladorAcmeDemoBundle:Bienvenida:index ser ejecutado. En la siguiente seccin, aprenders exactamente lo queeso significa.

8 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

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

Un controlador es un nombre elegante para una funcin o mtodo PHP que se encarga delas peticiones 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 es crear larespuesta a mano, basndote en la peticin:

use Symfony\Component\HttpFoundation\Response;

$nombre = $peticion->query->get(nombre);

return new Response(Hola .$nombre, 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 de _controller de la configuracin de enrutado:AcmeDemoBundle:Bienvenida:index. Esta cadena es el nombre lgico del controlador, y hace referenciaal mtodo indexAction de la clase Acme\DemoBundle\Controller\BienvenidaController:

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

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class BienvenidaController extends Controller{

public function indexAction(){

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

}

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

La clase BienvenidaController extiende la clase integrada Controller, la cual proporciona tiles atajosa mtodos, como el :method:Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render que cargay reproduce una plantilla (AcmeDemoBundle:Bienvenida:index.html.twing). El valor devuelto es unobjeto Respuesta poblado con el contenido reproducido. Por lo tanto, si surge la necesidad, la Respuesta sepuede ajustar antes de enviarla al navegador:

1.1. Un primer vistazo 9

Manual de Symfony2, Release 2.0.1

public function indexAction(){

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

return $respuesta;}

Pero en todos los casos, el trabajo final del controlador siempre es devolver 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 Controlller 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:Bienvenida:index.html.twig, es el nombre lgico dela plantilla y hace referencia al archivo Resources/views/Bienvenida/index.html.twig dentro delAcmeDemoBundle (ubicado en src/Acme/DemoBundle). En la seccin paquetes, a continuacin, explicar porqu 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("/hola/{nombre}", name="_demo_hola")

* @Template()

*/public function holaAction($nombre){

return array(nombre => $nombre);}

// ...}

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

10 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

Nota: Incluso si las anotaciones no son compatibles nativamente en PHP, las utilizamos ampliamente en Symfony2como 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:hola.html.twig (ubicada ensrc/Acme/DemoBundle/Resources/views/Demo/hola.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/hola.html.twig(o AcmeDemoBundle:Demo:hola.html.twig si utilizas el nombre lgico):

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

{% block titulo "Hola " ~ nombre %}

{% block contenido %}Hola {{ nombre }}!

{% 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

Manual de Symfony2, Release 2.0.1

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/hola/Nacho

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

http://localhost/Symfony/web/demo/hola/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 direcciones URL tengan un mejor aspecto:

12 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

http://localhost/demo/hola/Nacho

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 403) 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.

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.

1.2. La vista 13

Manual de Symfony2, Release 2.0.1

A continuacin mostramos una plantilla mnima que ilustra algunos conceptos bsicos, usando dos variablestitulo_pag y navegacion, mismas que se pasaron a la plantilla:

Mi pgina Web

{{ titulo_pag }}

{% for elemento in navegacion %}

{{ elemento.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:hola.html.twig, array(nombre => $nombre,

));

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(nombre => Fabien) #}{{ nombre }}

{# array(usuario => array(nombre => Fabien)) #}{{ usuario.nombre }}

{# obliga a verlo como arreglo #}{{ usuario[nombre] }}

{# array(usuario => new Usuario(Fabien)) #}{{ usuario.nombre }}{{ usuario.getNombre }}

{# obliga a ver el nombre como mtodo #}{{ usuario.nombre() }}{{ usuario.getNombre() }}

{# pasa argumentos al mtodo #}{{ usuario.fecha(Y-m-d) }}

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.

14 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

1.2.2 Decorando plantillas

Muy a menudo, las plantillas en un proyecto comparten elementos comunes, como los bien conocidos encabezados ypies de pgina. En Symfony2, nos gusta pensar en este problema de forma diferente: una plantilla se puede decorar conotra. Esto funciona exactamente igual que las clases PHP: la herencia de plantillas permite crear un diseo de plan-tilla bsico que contiene todos los elementos comunes de tu sitio y define bloques que las plantillas descendientespueden reemplazar.

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

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

{% block titulo "Hola " ~ nombre %}

{% block contenido %}Hola {{ nombre }}!

{% 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 contenido %}{% 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 hola.html.twig sustituye el bloque contenido, lo cual significa que el texto HolaFabien se reproduce dentro del elemento div.contenido-symfony.

1.2.3 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 integrada.html.twig:

{# src/Acme/DemoBundle/Resources/views/Demo/integrada.html.twig #}Hola {{ nombre }}

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

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

{# sustituye el bloque contenido con el de integrada.html.twig #}

1.2. La vista 15

Manual de Symfony2, Release 2.0.1

{% block contenido %}{% include "AcmeDemoBundle:Demo:integrada.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 maravillosa, y deseas incluirla dentro de la plantilla principal index.Para ello, utiliza la etiqueta render:

{# src/Acme/DemoBundle/Resources/views/Demo/index.html.twig #}{% render "AcmeDemoBundle:Demo:maravillosa" with { nombre: nombre, color: verde } %}

Aqu, la cadena AcmeDemoBundle:Demo:maravillosa se refiere a la accin maravillosa del con-trolador Demo. Los argumentos (nombre y color) actan como variables de la peticin simulada (como simaravillosaAction estuviera manejando una peticin completamente nueva) y se pone a disposicin del contro-lador:

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

class DemoController extends Controller{

public function maravillosaAction($nombre, $color){

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

return $this->render(AcmeDemoBundle:Demo:maravillosa.html.twig, array(nombre => $nombre, objeto => $objeto));}

// ...}

Creando enlaces entre pginas

Hablando de aplicaciones web, crear enlaces entre pginas es una necesidad. En lugar de codificar las direcciones URLen las plantillas, la funcin path sabe cmo generar direcciones URL basndose en la configuracin de enrutado. Deesta manera, todas tus direcciones URL se pueden actualizar fcilmente con slo cambiar la configuracin:

Hola Toms!

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 rutas:

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

/*** @Route("/hola/{nombre}", name="_demo_hola")

* @Template()

*/public function holaAction($nombre)

16 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

{return array(nombre => $nombre);

}

Truco: La funcin url genera direcciones URL absolutas: {{ url(_demo_hola, { nombre:Toms }) }}.

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.

1.2.4 Escapando variables

Twig se configura de forma automtica escapando toda salida de forma predeterminada. Lee la documentacin de Twigpara obtener ms informacin sobre el mecanismo de escape y la extensin Escaper.

1.2.5 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 es exacta-mente 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.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:

1.3. El controlador 17

Manual de Symfony2, Release 2.0.1

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

/*** @Route("/hola/{nombre}", defaults={"_format"="xml"}, name="_demo_hola")

* @Template()

*/public function holaAction($nombre){

return array(nombre => $nombre);}

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

{{ nombre }}

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("/hola/{nombre}.{_format}", defaults={"_format"="html"}, requirements={"_format"="html|xml|json"}, name="_demo_hola")

* @Template()

*/public function holaAction($nombre){

return array(nombre => $nombre);}

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

La entrada requirements define las expresiones regulares con las cuales los marcadores de posicin deben coin-cidir. En este ejemplo, si tratas de solicitar el recurso /demo/hola/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_hola, array(nombre => Lucas)));

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:

18 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

$respuesta = $this->forward(AcmeDemoBundle:Hola:maravillosa, array(nombre => $nombre, color => verde));

// 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:

$peticion = $this->getRequest();

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

$peticion->getPreferredLanguage(array(en, es));

$peticion->query->get(pag); // consigue un parmetro $_GET

$peticion->request->get(pag); // consigue 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:

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

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

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

// fija la configuracin regional del usuario$sesion->setLocale(es);

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

// guarda un mensaje para la siguiente peticin (en un controlador)$sesion->setFlash(aviso, Felicidades, tu accin fue exitosa!);

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

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. El controlador 19

Manual de Symfony2, Release 2.0.1

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:

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 comienza 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/hola automti-camente 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;

/*** @Route("/hola/admin/{nombre}", name="_demo_secured_hola_admin")

* @Secure(roles="ROLE_ADMIN")

* @Template()

20 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

*/public function holaAdminAction($nombre){

return array(nombre => $nombre);}

Ahora, inicia sesin como user (el cual no tiene el rol ROLE_ADMIN) y desde la pgina protegida hola, 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 181) 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("/hola/{nombre}", name="_demo_hola")

* @Template()

* @Cache(maxage="86400")

*/public function holaAction($nombre){

return array(nombre => $nombre);}

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 210) del libro.

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.3. El controlador 21

Manual de Symfony2, Release 2.0.1

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/: La configuracin de la aplicacin;

src/: El cdigo PHP del proyecto;

vendor/: Las dependencias de terceros;

web/: La raz del directorio 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;

$nucleo = new AppKernel(prod, false);$nucleo->loadClassCache();$nucleo->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:

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:

22 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

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

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

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

));$loader->registerPrefixes(array(

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

));

// ...

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

));$cargador->register();

La 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. Puedes guardarlas 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 la frmula Cmocargar clases automticamente (Pgina 407) en el recetario.

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.

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:

1.4. La arquitectura 23

Manual de Symfony2, Release 2.0.1

// 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 los archivos de configuracin escritos en YAML, XML o PHP. Echa unvistazo a la configuracin predeterminada:

# app/config/config.ymlimports:

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

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

default_locale:%locale%auto_start: true

# Configuracin Twigtwig:

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

# Configuracin de Assetic

24 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

assetic:debug: %kernel.debug%use_controller: falsefilters:

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%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, framework confi-gura 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 }

web_profiler:toolbar: trueintercept_redirects: false

monolog:handlers:

main:type: streampath: %kernel.logs_dir%/%kernel.environment%.log

1.4. La arquitectura 25

Manual de Symfony2, Release 2.0.1

level: debugfirephp:

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 el re-curso.

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:Bienvenida:index representa al mtodo indexAction de la claseAcme\DemoBundle\Controller\BienvenidaController.

Nombres lgicos de plantilla

Para las plantillas, el nombre lgico AcmeDemoBundle:Bienvenida:index.html.twig se convierte en laruta del archivo src/Acme/DemoBundle/Resources/views/Bienvenida/index.html.twig. Inclusolas plantillas son ms interesantes cuando te das cuenta que no es necesario almacenarlas en el sistema de archivos.Puedes guardarlas fcilmente en una tabla de la base de datos, por ejemplo.

Extendiendo paquetes

Si sigues estas convenciones, entonces puedes utilizar herencia de paquetes (Pgina 350) pa-ra redefinir archivos, controladores o plantillas. Por ejemplo, si un nuevo paquete llamadoAcmeNuevoBundle extiende el AcmeDemoBundle, entonces Symfony primero intenta cargar el controladorAcmeDemoBundle:Bienvenida:index de AcmeNuevoBundle, y luego ve dentro de AcmeDemoBundle.

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

26 Captulo 1. Gua de inicio rpido

Manual de Symfony2, Release 2.0.1

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- revisa el Libro (Pgina 33) oficial y elije cualquier tema que desees.

Un primer vistazo (Pgina 5) >

La vista (Pgina 13) >

El controlador (Pgina 17) >

La arquitectura (Pgina 22)

1.4. La arquitectura 27

Manual de Symfony2, Release 2.0.1

28 Captulo 1. Gua de inicio rpido

Parte II

Libro

29

Manual de Symfony2, Release 2.0.1

Sumrgete en Symfony2 con las guas temticas:

31

Manual de Symfony2, Release 2.0.1

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

Manual de Symfony2, Release 2.0.1

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

Manual de Symfony2, Release 2.0.1

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, /, /contacto, 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 Host solicitado,los formatos de respuesta que acepta el cliente (Accept) y la aplicacin que utiliza el cliente para realizar la peticin(User-Agent). Existen muchas otras cabeceras y se pueden encontrar en el artculo Lista de campos de las cabecerasHTTP 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

Manual de Symfony2, Release 2.0.1

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 devuelto 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 puede devol-ver en mltiples formatos, incluyendo HTML, XML o JSON por nombrar unos cuantos. La cabecera Content-Typeindica al cliente en qu formato se est devolviendo.

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:

Manual de Symfony2, Release 2.0.1

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: /probando?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 objeto del mensaje de la peticin HTTP. Con ella, tienes toda la informacin atu alcance:

use Symfony\Component\HttpFoundation\Request;

$peticion = Request::createFromGlobals();

// la URI solicitada (por ejemplo, /sobre) menos los parmetros de la consulta$peticion->getPathInfo();

// recupera las variables GET y POST respectivamente$peticion->query->get(foo);$peticion->request->get(bar);

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

$peticion->getMethod(); // GET, POST, PUT, DELETE, HEAD$peticion->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).

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;$respuesta = new Response();

$respuesta->setContent(Hola mundo!);$respuesta->setStatusCode(200);$respuesta->headers->set(Content-Type, text/html);

// imprime las cabeceras HTTP seguidas por el contenido$respuesta->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 apropiada basada en la lgica de tu aplicacin.

Truco: Las clases Respuesta y Peticin forman parte de un componente independiente incluido en Symfony

2.1. Symfony2 y fundamentos HTTP 37

Manual de Symfony2, Release 2.0.1

llamado 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.

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 los vnculos?) 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 solucin mucho mejor 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/contacto ejecuta index.php/index.php/blog ejecuta index.php

Truco: Usando mod_rewrite de Apache (o equivalente con otros servidores web), las direcciones URL se puedenlimpiar fcilmente hasta ser slo /, /contacto y /blog.

Ahora, cada peticin se maneja exactamente igual. En lugar de direcciones URL individuales ejecutando diferentesarchivos PHP, el controlador frontal siempre se ejecuta, y el enrutado de diferentes direcciones URL a diferentes partesde tu aplicacin se realiza internamente. Esto resuelve los problemas del enfoque original. Casi todas las aplicacionesweb modernas lo hacen - incluyendo aplicaciones como WordPress.

Mantente organizado

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

// index.php

$peticion = Request::createFromGlobals();$ruta = $peticion->getPathInfo(); // la URL solicitada

38 Captulo 2. Libro

Manual de Symfony2, Release 2.0.1

if (in_array($ruta, array(, /)) {$respuesta = new Response(Bienvenido a la pgina inicial.);

} elseif ($ruta == /contacto) {$respuesta = new Response(Contctanos);

} else {$respuesta = new Response(Pgina no encontrada., 404);

}$respuesta->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:

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 direc-ciones URL a diferentes funciones PHP. El trabajo de cada funcin PHP conocida como controlador, es utilizar lainformacin de la peticin - junto con muchas otras herramientas que Symfony pone a tu disposicin - para crear ydevolver un objeto Respuesta. En otras palabras, el controlador es donde est tu cdigo: ah es dnde se interpretala peticin y crea una 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/contacto a tu aplicacin Symfony. En primer lugar, empezamos agregando una entrada /contacto a tu archivo

2.1. Symfony2 y fundamentos HTTP 39

Manual de Symfony2, Release 2.0.1

de configuracin de enrutado:

contacto:pattern: /contactodefaults: { _controller: AcmeDemoBundle:Principal:contacto }

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

Cuando alguien visita la pgina /contacto, esta ruta coincide, y se ejecuta el controlador especificado. Como vere-mos en el captulo Enrutando (Pgina 81), La cadena AcmeDemoBundle:Principal:contacto es una sintaxiscorta que apunta hacia el mtodo PHP contactoAction dentro de una clase llamada PrincipalController:

class PrincipalController{

public function contactoAction(){

return new Response(Contctanos!);}

}

En este ejemplo muy simple, el controlador simplemente crea un objeto Respuesta con el cdigo HTMLContctanos!. En el captulo Controlador (Pgina 71), aprenders cmo un controlador puede repro-ducir plantillas, permitiendo que tu cdigo de presentacin (es decir, algo que en realidad escribe HTML) viva en unarchivo de plantilla separado. Esto libera al controlador de preocuparse slo de las cosas difciles: la interaccin conla 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 cosasen 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 nombraralgunos:

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

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

Form - Una completa y flexible plataforma para crear formularios y manipular la presentacin de los mismos;

40 Captulo 2. Libro

Manual de Symfony2, Release 2.0.1

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 permite utilizar clases PHP sin necesidad de requerirmanualmente 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.

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 muestra las entradas del blog que se han persistido en la base de datos. Escribirla en PHP simple es rpidoy sucio:

2.2. Symfony2 frente a PHP simple 41

Manual de Symfony2, Release 2.0.1

Lista de comunicados

Lista de comunicados

Manual de Symfony2, Release 2.0.1

mysql_select_db(bd_blog, $enlace);

$resultado = mysql_query(SELECT id, titulo FROM comunicado, $enlace);

$comunicados = array();while ($fila = mysql_fetch_assoc($resultado)) {

$comunicados[] = $fila;}

mysql_close($enlace);

// incluye el cdigo HTML de la presentacinrequire plantillas/lista.php;

Ahora el cdigo HTML est guardado en un archivo separado (plantillas/lista.php), el cual principalmentees un archivo HTML que utiliza una sintaxis de plantilla tipo PHP:

Lista de comunicados

Lista de comunicados

Manual de Symfony2, Release 2.0.1

return $enlace;}

function cierra_conexion_bd($enlace){

mysql_close($enlace);}

function obt_comunicados(){

$enlace = abre_conexion_bd();

$resultado = mysql_query(SELECT id, titulo FROM comunicado, $enlace);$comunicados = array();while ($fila = mysql_fetch_assoc($resultado)) {

$comunicados[] = $fila;}cierra_conexion_bd($enlace);

return $comunicados;}

Truco: Utilizamos el nombre de archivo modelo.php debido a que el acceso a la lgica y los datos de una apli-cacin, tradicionalmente, se conoce como la capa del modelo. En una aplicacin bien organizada, la mayora delcdigo que representa tu lgica de negocio debe vivir en el modelo (en lugar de vivir en un controlador). Y, a di-ferencia de este ejemplo, slo una parte (o ninguna) del modelo realmente est interesada en acceder a la base dedatos.

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

44 Captulo 2. Libro

Manual de Symfony2, Release 2.0.1

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

Lista de comunicados

Manual de Symfony2, Release 2.0.1

require plantillas/show.php;

Por ltimo, crea el nuevo archivo de plantilla - plantillas/show.php - para reproducir una entrada individualdel blog:

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 modelo.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

La solucin es utilizar un controlador frontal: un nico archivo PHP a travs del cual se procesan todas las 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.php

46 Captulo 2. Libro

Manual de Symfony2, Release 2.0.1

ahora 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:

Manual de Symfony2, Release 2.0.1

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/. A continuacin, crea un archivoapp/bootstrap.php. Se usa para requerir los dos archivos en la aplicacin y para configurar el cargadorautomtico:

Manual de Symfony2, Release 2.0.1

// controladores.phpuse Symfony\Component\HttpFoundation\Response;

function lista_action(){

$comunicados = obt_comunicados();$html = reproduce_plantilla(plantillas/lista.php, array(comunicados => $comunicados));

return new Response($html);}

function show_action($id){

$comunicado = obt_comunicado_por_id($id);$html = reproduce_plantilla(plantillas/show.php, array(post => $comunicado));

return new Response($html);}

// funcin ayudante para reproducir plantillasfunction reproduce_plantilla($ruta, array $args){

extract($args);ob_start();require $ruta;$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 sonsimples, esta flexibilidad pagar dividendos en cuanto tu aplicacin crezca.

Aplicacin de ejemplo en Symfony2

El blog ha avanzado, pero todava contiene una gran cantidad de cdigo para una aplicacin tan simple. De paso,tambin inventamos un sencillo sistema de enrutado y un mtodo que utiliza ob_start() y ob_get_clean()para procesar plantillas. Si, por alguna razn, necesitas continuar la construccin de esta pla