Symfony 1.0, 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 encuentran en el archivo $sf_symfony_data_dir/config/constants.php, que se incluye cuando se inicia la aplicación. Todas estas variables se almacenan en el objeto sfConfig, por lo que es muy fácil redefinir sus valores. El listado 19-3 muestra las variables que almacenan las rutas y el directorio al que hacen referencia.

Listado 19-3 - Variables de la estructura de archivos por defecto, en $sf_symfony_data_dir/config/constants.php

sf_root_dir           # miproyecto/
                      #   apps/
sf_app_dir            #     miaplicacion/
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_bin_dir            #   batch/
                      #   cache/
sf_base_cache_dir     #     miaplicacion/
sf_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_model_lib_dir      #     model/
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 SF_ROOT_DIR.'/web/uploads/'.

La estructura de directorios de los módulos se define durante la ejecución de la aplicación, cuando el sistema de enrutamiento determina el nombre del módulo ($module_name). La estructura de directorios se construye automáticamente en función de las rutas definidas en el archivo constants.php, como se muestra en el listado 19-4.

Listado 19-4 - Default Module File Structure Variables

sf_app_module_dir                 # modules/
module_name                       #  mimodelo/
sf_app_module_action_dir_name     #    actions/
sf_app_module_template_dir_name   #    templates/
sf_app_module_lib_dir_name        #    lib/
sf_app_module_view_dir_name       #    views/
sf_app_module_validate_dir_name   #    validate/
sf_app_module_config_dir_name     #    config/
sf_app_module_i18n_dir_name       #    i18n/

De esta forma, la ruta por ejemplo al directorio validate/ del módulo actual se construye de forma dinámica durante la ejecución de la aplicación de la siguiente forma:

sfConfig::get('sf_app_module_dir').'/'.$module_name.'/'.sfConfig::get('sf_app_module_validate_dir_name')

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 las variables sf_XXX_dir y sf_XXX_dir_name mediante sfConfig, se puede conseguir que Symfony funcione correctamente con una estructura de directorios completamente diferente a la de por defecto. El mejor archivo para modificar estas variables es el archivo config.php de la aplicación.

Advertencia Para redefinir las variables sf_XXX_dir y sf_XXX_dir_name mediante sfConfig, se debería utilizar el archivo config.php de la aplicación y no el del proyecto. El archivo config/config.php del proyecto se carga muy al principio de cada petición, cuando la clase sfConfig todavía no está disponible y por tanto, cuando el archivo constants.php no se ha cargado todavía.

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 archivo miaplicacion/config/config.php para redefinir la opción sf_app_template_dir:

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

El archivo config.php de la aplicación no está vacío, por lo que si se necesitan incluir las definiciones de la estructura de archivos, se deben añadir al final del archivo.

19.3.3. Modificando el directorio raíz del proyecto

Todas las rutas construidas en constants.php se basan en el directorio raíz del proyecto, que es una constante que se define en el controlador frontal (SF_ROOT_DIR). 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 2 directorios, uno puede ser el directorio público y otro el privado, tal y como muestra el listado 19-5. Esta estructura es muy típica cuando se utiliza un servicio de hosting compartido.

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

symfony/    # Area privada
  apps/
  batch/
  cache/
  ...
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 (archivo index.php) se debe definir la variable SF_ROOT_DIR de la siguiente forma:

define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony');

Además, como el área pública es www/ en vez del tradicional web/, se debe redefinir el valor de las rutas a 2 archivos en el archivo de configuración config.php de la aplicación:

sfConfig::add(array(
      'sf_web_dir'      => SF_ROOT_DIR.'/../www',
      'sf_upload_dir'   => SF_ROOT_DIR.'/../www/'.sfConfig::get('sf_upload_dir_name'),
    ));

19.3.4. Enlazando las librerías de Symfony

Como se ve en el listado 19-6, el archivo config.php también define las rutas a los archivos del framework.

Listado 19-6 - Las rutas a los archivos del framework, en miproyecto/config/config.php

<?php

// Directorios de Symfony
$sf_symfony_lib_dir  = '/ruta/a/symfony/lib';
$sf_symfony_data_dir = '/ruta/a/symfony/data';

Estas rutas se inicializan cuando se ejecuta la tarea symfony init-project desde la línea de comandos y hacen referencia a la instalación de Symfony que se ha utilizado para construir el proyecto. Las dos rutas 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 las rutas a los archivos de Symfony.

Aunque estas rutas pueden ser absolutas, 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/symfony/ del proyecto, al igual que el directorio data/:

miproyecto/
  lib/
    symfony/ => /ruta/a/symfony/lib
  data/
    symfony/ => /ruta/a/symfony/data

En este caso, en el archivo config.php del proyecto se deben definir los directorios de Symfony de la siguiente manera:

$sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/symfony';
$sf_symfony_data_dir = dirname(__FILE__).'/../data/symfony';

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

En este caso, el archivo config.php debería ser:

$sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/vendor/symfony/lib';
$sf_symfony_data_dir = dirname(__FILE__).'/../lib/vendor/symfony/data';

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 config.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 de producción del archivo config.php y que las rutas apunten a enlaces simbólicos que cambian en cada servidor.