Symfony 2.3, el libro oficial

1.4. El viaje desde la petición hasta la respuesta

Al igual que el mismo HTTP, los objetos Petición y Response son bastante simples. La parte difícil de la construcción de una aplicación es escribir lo que viene en el medio.

En otras palabras, el verdadero trabajo viene al escribir el código que interpreta la información de la petición y crea la respuesta.

Tu aplicación probablemente hace muchas cosas, como enviar correo electrónico, manejar los formularios presentados, guardar cosas en una base de datos, reproducir las páginas HTML y proteger el contenido con seguridad. ¿Cómo puedes manejar todo esto y al mismo tiempo conseguir que tu código esté organizado y sea fácil de mantener?

Symfony fue creado precisamente para resolver estos problemas y para que no tengas que hacerlo a mano.

1.4.1. El controlador frontal

Antiguamente, las aplicaciones web se construían de modo que cada página web del sitio tenía su propio archivo físico:

index.php
contacto.php
blog.php

Esta filosofía de trabajo tiene varios problemas, como la falta de flexibilidad de las URL (¿qué pasa si quieres cambiar blog.php a noticias.php sin romper todos tus enlaces?) y el hecho de que cada archivo debe incluir a mano todos los archivos necesarios para la seguridad, conexiones a base de datos y para aplicar los estilos gráficos del sitio.

Una solución mucho mejor es usar un controlador frontal, que es un solo archivo PHP que se encarga de servir todas las peticiones que llegan a tu aplicación. Por ejemplo:

Archivo solicitado Archivo realmente ejecutado
/index.php index.php
/index.php/contacto index.php
/index.php/blog index.php

Truco Usando el módulo mod_rewrite de Apache (o el equivalente en otros servidores web), las URL se pueden limpiar fácilmente para que quiten la parte del index.php y se queden simplemente en /, /contacto y /blog.

Ahora, todas las peticiones se manejan exactamente igual. En lugar de URL individuales ejecutando diferentes archivos PHP, el controlador frontal siempre se ejecuta, y la redirección de cada URL a una parte diferente de la aplicación se realiza internamente. Esto resuelve los problemas comentados anteriormente.

Casi todas las aplicaciones web modernas siguen la filosofía del controlador frontal, incluyendo aplicaciones como WordPress.

1.4.2. Mantente organizado

Una vez dentro del controlador frontal, ¿cómo sabes qué página debes generar y cómo puedes generar todas las páginas sin que la aplicación se vuelva caótica? El truco consiste en comprobar la URI entrante y ejecutar diferentes partes de tu código en función de ese valor. Aunque es bastante chapucero, el siguiente código te podría servir para ello:

// Contenido del archivo index.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

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

if (in_array($path, array('', '/')) {
    $response = new Response('Bienvenido a nuestra portada.');
} elseif ($path == '/contacto') {
    $response = new Response('Contáctanos');
} else {
    $response = new Response('Página no encontrada.', 404);
}
$response->send();

Escalar el código anterior para una aplicación real es un problema difícil de resolver. Afortunadamente esto es exactamente para lo que Symfony está diseñado.

1.4.3. El flujo de las aplicaciones Symfony

Cuando dejas que Symfony controle cada petición, tu vida como programador es mucho más fácil. Symfony sigue el mismo patrón simple en cada petición. Las peticiones entrantes son interpretadas por el enrutador y pasadas a las funciones controladoras, que devuelven objetos Response.

Flujo de la petición en Symfony2

Figura 1.4 Flujo de la petición en Symfony2

Cada página de tu sitio está definida en un archivo de configuración de rutas que asigna a cada URL una función PHP diferente. El trabajo de cada función PHP (conocida como controlador), es utilizar la información de la petición — junto con muchas otras herramientas que Symfony pone a tu disposición — para crear y devolver un objeto Response. En otras palabras, el controlador es donde está tu código: ahí es dónde se interpreta la petición y se crea una respuesta. ¡Así de fácil!

Repasemos:

  • Cada petición ejecuta un archivo controlador frontal;
  • El sistema de enrutado determina qué función PHP se ejecuta en base a la información de la petición y la configuración de enrutado que hemos creado;
  • Se ejecuta la función PHP adecuada, donde tu código crea y devuelve el objeto Response.

1.4.4. Una petición Symfony en la práctica

Sin entrar demasiado en los detalles, veamos este proceso en la práctica. Supongamos que deseas agregar una página /contacto a tu aplicación Symfony. En primer lugar, empezamos agregando una entrada /contacto a tu archivo de configuración de rutas:

# app/config/routing.yml
contacto:
    path:     /contacto
    defaults: { _controller: AcmeDemoBundle:Main:contacto }
<route id="contacto" path="/contacto">
    <default key="_controller">AcmeBlogBundle:Main:contacto</default>
</route>
// app/config/routing.php
        use Symfony\Component\Routing\RouteCollection;
        use Symfony\Component\Routing\Route;

        $collection = new RouteCollection();
        $collection->add('contacto', new Route('/contacto', array(
            '_controller' => 'AcmeBlogBundle:Main:contacto',
        )));

        return $collection;

Nota En este ejemplo utilizamos YAML para definir la configuración de enrutado, pero también se pueden utilizar los formatos XML y PHP.

Cuando alguien visita la página /contacto, Symfony2 detecta que se trata de esta ruta y se ejecuta el controlador especificado. Como veremos en el capítulo de enrutamiento, la cadena AcmeDemoBundle:Main:contacto es un atajo que apunta al método contactoAction() de PHP dentro de una clase llamada MainController:

// src/Acme/DemoBundle/Controller/MainController.php
namespace Acme\DemoBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class MainController
{
    public function contactoAction()
    {
        return new Response('<h1>Contáctanos</h1>');
    }
}

En este ejemplo sencillo, el controlador simplemente crea un objeto Response con el código HTML "<h1>Contáctanos</h1>". En el capítulo dedicado a los controladores aprenderás cómo hacer que los controladores utilicen plantillas para generar el contenido HTML en vez de tener que escribirlo directamente en el objeto Response. Esto hace que el controlador deba preocuparse sólo de las cosas difíciles: la interacción con la base de datos, la manipulación de la información o el envío de mensajes de correo electrónico.