La nueva arquitectura de Symfony 1.1

NOTA: Este artículo es una traducción del original The symfony 1.1 architecture, publicado el 23 de junio de 2008 en el blog oficial de Symfony.

La versión 1.1 del framework Symfony está formada por varias clases relacionadas entre sí pero completamente desacopladas, lo que se conoce con el nombre de plataforma Symfony:

Esquema gráfico de las clases que componen la plataforma Symfony

Cada una de las clases de la plataforma Symfony se puede utilizar de forma independiente al resto de la arquitectura MVC. Las clases de la plataforma Symfony no tienen ninguna dependencia y la única condición para utilizarlas es registrar el cargador automático de clases de Symfony:

require_once '/ruta/hasta/sfCoreAutoload.class.php';
sfCoreAutoload::register();

Incluyendo solamente las dos líneas de código anteriores, tu aplicación puede utilizar cualquiera de las clases de la plataforma Symfony. Si por ejemplo alguno de tus proyectos no utiliza Symfony pero quieres hacer uso de la clase sfYaml para procesar archivos en formato YAML, sólo tienes que incluir el cargador automático de clases:

require_once '/ruta/hasta/sfCoreAutoload.class.php';
sfCoreAutoload::register();

// Cargar una cadena o archivo en formato YAML
$configuracion = sfYaml::load('/ruta/hasta/un/archivo.yml');
$configuracion = sfYaml::load(<<<EOF
configuracion:
clave: valor
clave1: [valor1, valor 2]
clave2: { subclave1: subvalor1 }
EOF);

// Convertir un array en una cadena en formato YAML
$yaml = sfYaml::dump($configuracion);

El mismo proceso se puede utilizar para cualquier otra clase, como por ejemplo las clases de sfCache:

require_once '/ruta/hasta/sfCoreAutoload.class.php';
sfCoreAutoload::register();

$cache = new sfSQLiteCache(array('database' => dirname(__FILE__).'/cache.db'));
$cache->set('clave', 'valor');
$valor = $cache->get('clave');

En el ejemplo anterior se utilizar la base de datos SQLite como almacenamiento de la cache, pero recuerda que Symfony también permite utilizar archivos, APC, XCache, eAccelerator y Memcache.

Aunque resulta evidente utilizar las dos clases anteriores de forma independiente, la plataforma Symfony va un poco más allá cuando se utilizan las clases sfRequest y sfResponse. A continuación se muestra un ejemplo que utiliza estas dos clases para crear un script sencillo que muestra el mensaje “Hola Mundo”:

require_once '/ruta/hasta/sfCoreAutoload.class.php';
sfCoreAutoload::register();

$dispatcher = new sfEventDispatcher();

$peticion = new sfWebRequest($dispatcher);
$respuesta = new sfWebResponse($dispatcher);

$contenido = 'Hola '.$peticion->getParameter('nombre', 'Mundo');

$respuesta->setContent($contenido);
$respuesta->send();

El ejemplo anterior utiliza el objeto sfEventDispatcher. Aunque las clases de la plataforma Symfony están totalmente desacopladas, el dispatcher permite que algunas de sus clases se comuniquen entre sí. El dispatcher notifica eventos y permite suscribirse a los eventos producidos.

Para crear un listener no es necesario implementar una interfaz y tampoco es necesario utilizar ninguna clase base para crear un evento. Los eventos se definen mediante su nombre y un array de parámetros enviados por el notificador del evento.

La clase sfPatterRouting por ejemplo escucha el evento request.filter_parameters:

$llamada = array($this, 'filterParameters');
$dispatcher->connect('request.filter_parameters', $llamada);

Cuando se crea una petición, sfWebRequest notifica el evento request.filter_parameters:

$evento = new sfEvent($this, 'request.filter_parameters');
$parametros = $dispatcher->filter($evento, $parametros);

Por lo tanto, aunque las clases sfWebRequest y sfPatternRouting están desacopladas, se comunican de forma automágica cuando comparten el mismo dispatcher.

Para mostrar esta característica, se va a modificar el ejemplo anterior añadiendo un objeto de tipo enrutamiento para conectar el patrón /hola/:nombre a la aplicación “Hola Mundo”:

require_once '/ruta/hasta/sfCoreAutoload.class.php';
sfCoreAutoload::register();

$dispatcher = new sfEventDispatcher();

$enrutamiento = new sfPatternRouting($dispatcher);
$enrutamiento->connect('hola', '/hola/:nombre');

$peticion = new sfWebRequest($dispatcher);
$respuesta = new sfWebResponse($dispatcher);

$contenido = 'Hola '.$peticion->getParameter('nombre', 'Mundo');

$respuesta->setContent($contenido);
$respuesta->send();

Si se guarda el código anterior en un archivo llamado index.php dentro de la carpeta raíz del servidor web, se puede acceder a la aplicación mediante una URL del tipo /index.php/hola/Fabien

La gran ventaja de la plataforma Symfony es que puedes utilizar algunas de las utilidades que incluye sin la obligación de utilizar toda la arquitectura MVC completa.

Además, también puedes migrar tus viejas aplicaciones a Symfoy utilizando este mecanismo. En vez de reescribir tus aplicaciones desde cero, puedes ir añadiendo algunas características de Symfony poco a poco.

Utilizando la plataforma Symfony es posible incluso crear tu propio framework. Para ello, no tienes que perder el tiempo creando los componentes básicos de un framework, ya que la plataforma Symfony te proporciona todo lo que necesitas para crear tu propio framework:

  • sfRequest/sfRouting para gestionar las peticiones
  • sfUser/sfStorage para gestionar las sesiones de usuario
  • sfForm para gestionar los formularios
  • sfCache para gestionar la cache
  • sfOutputEscaper para gestionar la protección contra ataques XSS
  • sfResponse para gestionar la respuesta

De hecho, el propio Symfony es un framework construido sobre la plataforma Symfony:

Esquema gráfico de las clases que añade el framework Symfony al resto de clases proporcionadas por la plataforma Symfony

La clase sfConfiguration permite configurar y personalizar cada aplicación. La clase sfContext se comporta como un registro que almacena las referencias a todos los objetos del núcleo del framework. Además, gracias al archivo de configuración factories.yml, se pueden personalizar fácilmente todas las clases del registro, simplemente editando un archivo YAML.

El framework MVC de Symfony se compone además de una serie de clases que hacen uso de sfContext y de otras clases de la plataforma Symfony:

Esquema gráfico de todas las clases principales del frameowrk Symfony y las de la plataforma Symfony

La capa del modelo hace uso de librerías externas como Propel y Doctrine. Aunque Symfony 1.1 incluye Propel en forma de plugin, es muy sencillo cambiar a Doctrine utilizando el plugin sfDoctrinePlugin. Los dos ORM disfrutan del mismo nivel de integración con Symfony.

La capa de la vista se realiza mediante la clase sfView, un conjunto de helpers y las plantillas creadas por el programador.

La capa del controlador se basa en una cadena de filtros y en las acciones creadas por el programador.

Conclusión

Symfony 1.1 es uno de los frameworks PHP más desacoplados que existen, incluso está más desacoplado que Zend Framework. Si se considera por ejemplo los formularios sfForm, se pueden utilizar sin hacer uso de ninguna otra clase de la arquitectura MVC, mientras que Zend_Form requiere el uso de clases de la capa del controlador y de la capa de la vista.