Symfony 1.4, la guía definitiva

17.3. Integrando componentes de otros frameworks

Si se requiere utilizar una clase externa y no se copia esa clase en algún directorio lib/ de Symfony, la clase se encontrará en algún directorio en el que Symfony no la puede encontrar. En este caso, si se utiliza esta clase en el código, es necesario incluir manualmente una instrucción require, a menos que se utilicen las propiedades de Symfony para enlazar y permitir la carga automática de otros componentes externos.

Symfony de momento no proporciona utilidades y herramientas para resolver cualquier tipo de problema. Si se necesita un generador de archivos PDF, una API para interactuar con los mapas de Google o una implementación en PHP del motor de búsqueda Lucene, es necesario hacer uso de algunas librerías del framework de Zend (http://framework.zend.com/). Si se quieren manipular imágenes directamente con PHP, conectarse con una cuenta POP3 para obtener los emails o diseñar una interfaz para la consola de comandos, seguramente se utilizarán los eZcomponents (http://ez.no/ezcomponents). Afortunadamente, si se utilizan las opciones correctas, se pueden utilizar directamente en Symfony todos los componentes de estas librerías externas.

Lo primero que hay que hacer es declarar la ruta al directorio raíz de cada librería en el archivo app.yml, a menos que las librerías se hayan instalado mediante PEAR.

all:
  zend_lib_dir:   /usr/local/zend/library/
  ez_lib_dir:     /usr/local/ezcomponents/
  swift_lib_dir:  /usr/local/swiftmailer/

A continuación, se extiende el mecanismo de carga automática de clases de PHP indicando que librería se debe utilizar cuando falle la carga automática de Symfony. Para ello, se registran las clases que se cargan de forma automática en la clase de configuración de la aplicación (el capítulo 19 lo explica en detalle) tal y como se muestra en el listado 17-9.

Listado 17-9 - Extendiendo el mecanismode carga automática de clases para permitir el uso de componentes externos, en apps/frontend/config/ApplicationConfiguration.class.php

class frontendConfiguration extends sfApplicationConfiguration
{
  public function initialize()
  {
    parent::initialize(); // primero la carga automática de Symfony

    // Integrando el Zend Framework
    if ($sf_zend_lib_dir = sfConfig::get('app_zend_lib_dir'))
    {
      set_include_path($sf_zend_lib_dir.PATH_SEPARATOR.get_include_path());
      require_once($sf_zend_lib_dir.'/Zend/Loader.php');
      spl_autoload_register(array('Zend_Loader', 'Zend_Loader'));
    }

    // Integrando eZ Components
    if ($sf_ez_lib_dir = sfConfig::get('app_ez_lib_dir'))
    {
      set_include_path($sf_ez_lib_dir.PATH_SEPARATOR.get_include_path());
      require_once($sf_ez_lib_dir.'/Base/base.php');
      spl_autoload_register(array('ezcBase', 'autoload'));
    }

    // Integrando Swift Mailer
    if ($sf_swift_lib_dir = sfConfig::get('app_swift_lib_dir'))
    {
      set_include_path($sf_swift_lib_dir.PATH_SEPARATOR.get_include_path());
      require_once($sf_swift_lib_dir.'/Swift/ClassLoader.php');
      spl_autoload_register(array('Swift_ClassLoader', 'load'));
    }
  }
}

A continuación se describe lo que sucede cuando se crea un nuevo objeto de una clase que no ha sido cargada:

  1. La función de Symfony encargada de la carga automática de clases busca la clase en las rutas especificadas en el archivo autoload.yml.
  2. Si no se encuentra ninguna clase, se invocan uno a uno los métodos registrados con spl_autoload_register() hasta que uno de ellos devuelva el valor true. Por lo tanto, se invocan los métodos Zend_Loader::autoload(), ezcBase::autoload() y Swift_ClassLoader::load() hasta que alguno de ellos encuentre la clase.
  3. Si todos los métodos anteriores devuelven false, PHP genera un error.

De esta forma, los componentes de otros frameworks pueden aprovecharse también del mecanismo de carga automática de clases, por lo que es incluso más sencillo que utilizarlos dentro de los frameworks originales. El siguiente código muestra por ejemplo cómo utilizar el componente Zend_Search (que implementa el motor de búsqueda Lucene en PHP) desde el propio framework Zend:

require_once 'Zend/Search/Lucene.php';
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
// ...

Utilizando Symfony y la carga automática de clases, es mucho más fácil utilizar este componente. De hecho, no es necesario utilizar ningún require y por tanto no tienes que preocuparte de las rutas de los archivos y de las clases:

$doc = new Zend_Search_Lucene_Document(); // The class is autoloaded
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
// ...