Symfony 1.1, la guía definitiva

19.3. Estructura de archivos propia

Cada vez que el framework requiere de una ruta para buscar algo (las clases internas de Symfony, las plantillas, los plugins, los archivos de configuración, etc.) utiliza una variable que almacena la ruta. Modificando el valor de estas variables, se puede modificar por completo la estructura de directorios de un proyecto Symfony, para adaptarla a las necesidades específicas de cualquier cliente.

Truco Aunque es posible modificar por completo la estructura de directorios de los proyectos Symfony, no se recomienda hacerlo. Uno de los puntos fuertes de los frameworks como Symfony es que cualquier programador puede comprender fácilmente cualquier proyecto desarrollado con Symfony, debido al uso de las convenciones. Por tanto, debe considerarse seriamente las ventajas y desventajas de modificar la estructura de directorios antes de hacerlo.

19.3.1. La estructura de archivos básica

Las variables que almacenan las rutas utilizadas se definen en las clases sfProjectConfiguration y sfApplicationConfiguration y se almacenan en el objeto sfConfig. El listado 19-5 muestra las variables que almacenan las rutas y el directorio al que hacen referencia.

Listado 19-5 - Variables de la estructura de archivos por defecto, definidas en sfProjectConfiguration y sfApplicationConfiguration

sf_root_dir           # myproject/
sf_apps_dir           #   apps/
sf_app_dir            #     frontend/
sf_app_config_dir     #       config/
sf_app_i18n_dir       #       i18n/
sf_app_lib_dir        #       lib/
sf_app_module_dir     #       modules/
sf_app_template_dir   #       templates/
sf_cache_dir          #   cache/
sf_app_base_cache_dir #     frontend/
sf_app_cache_dir      #       prod/
sf_template_cache_dir #         templates/
sf_i18n_cache_dir     #         i18n/
sf_config_cache_dir   #         config/
sf_test_cache_dir     #         test/
sf_module_cache_dir   #         modules/
sf_config_dir         #   config/
sf_data_dir           #   data/
sf_doc_dir            #   doc/
sf_lib_dir            #   lib/
sf_log_dir            #   log/
sf_test_dir           #   test/
sf_plugins_dir        #   plugins/
sf_web_dir            #   web/
sf_upload_dir         #     uploads/

Todas las rutas a los directorios principales de Symfony se obtienen a través de opciones acabadas en _dir. Siempre se deberían utilizar las variables en vez de las rutas reales (absolutas o relativas), de forma que se puedan modificar posteriormente si es necesario. Si se quiere por ejemplo mover un archivo al directorio uploads/ de la aplicación, se debería utilizar como ruta el valor sfConfig::get('sf_upload_dir') en vez de sfConfig::get('sf_root_dir').'/web/uploads/'

19.3.2. Modificando la estructura de archivos

Si se desarrolla una aplicación para un cliente que ya dispone de una estructura de directorios definida y que no quiere cambiarla para adaptarse a Symfony, será necesario modificar la estructura de archivos por defecto. Redefiniendo el valor de la variable sf_XXX_dir mediante sfConfig, se puede conseguir que Symfony funcione correctamente con una estructura de directorios completamente diferente a la de por defecto. El mejor lugar para realizar esta modificación es la clase ProjectConfiguration de la aplicación para los directorios del proyecto y la clase XXXConfiguration para los directorios de la aplicaciones.

Si por ejemplo se necesita que todas las aplicaciones compartan un directorio común para los layouts de las plantillas, se añade la siguiente línea en el método configure() de la clase ProjectConfiguration para redefinir la opción sf_app_template_dir:

sfConfig::set('sf_app_template_dir', sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.'templates');

Nota Aunque se puede modificar la estructura de directorios del proyecto mediante el método sfConfig::set(), es mejor utilizar los métodos definidos por las clases de configuración del proyecto y de las aplicaciones, ya que también se encargan de modificar todas las rutas relacionadas. El método setCacheDir() por ejemplo modifica los valores de sf_cache_dir, sf_app_base_cache_dir, sf_app_cache_dir, sf_template_cache_dir, sf_i18n_cache_dir, sf_config_cache_dir, sf_test_cache_dir y sf_module_cache_dir.

19.3.3. Modificando el directorio raíz del proyecto

Todas las rutas definidas en las clases de configuración se basan en el directorio raíz del proyecto, que se define en el archivo ProjectConfiguration incluído en el controlador frontal. Normalmente, el directorio raíz se encuentra un nivel por encima del directorio web/, pero se puede utilizar una estructura diferente. Si se utiliza una estructura principal de directorios formada por dos directorios, uno puede ser el directorio público y otro el privado, tal y como muestra el listado 19-7. Esta estructura es muy típica cuando se utiliza un servicio de hosting compartido.

Listado 19-7 - Ejemplo de estructura de directorios propia en un hosting compartido

symfony/    # Area privada
  apps/
  config/
  ...
www/        # Area pública
  images/
  css/
  js/
  index.php

En este caso, el directorio raíz sería el directorio symfony/. De esta forma, para que la aplicación funcione correctamente, en el controlador frontal index.php se debe incluir el archivo config/ProjectConfiguration.class.php de la siguiente forma:

require_once(dirname(__FILE__).'/../symfony/config/ProjectConfiguration.class.php');

Además, como el área pública es www/ en vez del tradicional web/, se debe redefinir su valor con el método setWebDir():

class ProjectConfiguration extends sfProjectConfiguration
{
  public function configure()
  {
    // ...

    $this->setWebDir($this->getRootDir().'/../www');
  }
}

19.3.4. Enlazando las librerías de Symfony

La ruta a los archivos del framework se define en la clase ProjectConfiguration, que se encuentra en el directorio config/, tal y como se muestra en el listado 19-8.

Listado 19-8 - Las ruta a los archivos del framework, en miproyecto/config/ProjectConfiguration.class.php

<?php

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

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
  }
}

La ruta se inicializa cuando se ejecuta la tarea php symfony generate:project desde la línea de comandos y hace referencia a la instalación de Symfony que se ha utilizado para construir el proyecto. La ruta se utilizan tanto en la línea de comandos como en la arquitectura MVC.

Por tanto, se puede utilizar otra instalación de Symfony simplemente modificando la ruta a los archivos de Symfony.

Aunque esta ruta puede ser absoluta, también es posible utilizar dirname(__FILE__) para hacer referencia a archivos dentro de la estructura del proyecto y para mantener la independencia respecto al directorio elegido para instalar el proyecto. Muchos proyectos prefieren por ejemplo que el directorio lib/ de Symfony aparezca como un enlace simbólico en el directorio lib/vendor/symfony/ del proyecto:

miproyecto/
  lib/
    vendor/
      symfony/ => /ruta/hasta/symfony/

En este caso, la clase ProjectConfiguration sólo debe definir el directorio lib/ de Symfony de la siguiente manera:

<?php

require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
  }
}

El mismo principio se aplica si se quieren incluir los archivos de Symfony como svn:externals en el directorio lib/vendor/ del proyecto:

miproyecto/
  lib/
    vendor/
      svn:externals symfony http://svn.symfony-project.com/branches/1.1

Truco En ocasiones, los diferentes servidores que ejecutan las aplicaciones no tienen las librerías de Symfony en las mismas rutas. Una forma de conseguirlo es excluir el archivo ProjectConfiguration.class.php del proceso de sincronización (añadiéndolo a la lista del archivo rsync_exclude.txt). Otra forma de hacerlo es mantener las mismas rutas en la versión de desarrollo y en la versión de producción del archivo ProjectConfiguration.class.php y que las rutas apunten a enlaces simbólicos que cambian en cada servidor.