Symfony 1.0, la guía definitiva

9.2. Reescritura de URL

Antes de adentrarse en el funcionamiento interno del sistema de enrutamiento, se debe aclarar una cuestión importante. En los ejemplos mostrados en las secciones anteriores, las URI internas no incluyen el controlador frontal (index.php o miapp_dev.php). Como se sabe, es el controlador frontal y no otros elementos de la aplicación, el que decide el entorno de ejecución. Por este motivo, todos los enlaces deben ser independientes del entorno de ejecución y el nombre del controlador frontal nunca aparece en las URI internas.

Además, tampoco se muestra el nombre del script PHP en las URL generadas en los ejemplos anteriores. La razón es que, por defecto, las URL no contienen el nombre de ningún script de PHP en el entorno de producción. El parámetro no_script_name del archivo settings.yml controla la aparición del nombre del controlador frontal en las URL generadas. Si se establece su valor a off, como se muestra en el listado 9-5, las URL generadas por los helpers incluirán el nombre del script del controlador frontal en cada enlace.

Listado 9-5 - Mostrando el nombre del controlador frontal en las URL, en apps/miapp/config/settings.yml

prod:
  .settings
    no_script_name:  off

Ahora, las URL generadas tienen este aspecto:

http://www.ejemplo.com/index.php/articulos/economia/2006/sectores-actividad.html

En todos los entornos salvo en el de producción, el parámetro no_script_name tiene un valor igual a off por defecto. Si se prueba la aplicación en el entorno de desarrollo, el nombre del controlador frontal siempre aparece en las URL.

http://www.ejemplo.com/miapp_dev.php/articulos/economia/2006/sectores-actividad.html

En el entorno de producción, la opción no_script_name tiene el valor de on, por lo que las URL solo muestran la información necesaria para el enrutamiento y son más sencillas para los usuarios. No se muestra ningún tipo de información técnica.

http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html

¿Cómo sabe la aplicación el nombre del script del controlador frontal que tiene que ejecutar? En este punto es donde comienza la reescritura de URL. El servidor web se puede configurar para que se llame siempre a un mismo script cuando la URL no indica el nombre de ningún script.

En el servidor web Apache se debe tener activado previamente el módulo mode_rewrite. Todos los proyectos de Symfony incluyen un archivo llamado .htaccess que añade las opciones necesarias para el mod_rewrite de Apache en el directorio web/. El contenido por defecto de este archivo se muestra en el listado 9-6.

Listado 9-6 - Reglas de reescritura de URL por defecto para Apache, en miproyecto/web/.htaccess

<IfModule mod_rewrite.c>
  RewriteEngine On

  # we skip all files with .something
  # comment the following 3 lines to allow periods in routes
  RewriteCond %{REQUEST_URI} \..+$
  RewriteCond %{REQUEST_URI} !\.html$
  RewriteRule .* - [L]

  # we check if the .html version is here (caching)
  RewriteRule ^$ index.html [QSA]
  RewriteRule ^([^.]+)$ $1.html [QSA]
  RewriteCond %{REQUEST_FILENAME} !-f

  # no, so we redirect to our front web controller
  RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

El servidor web analiza la estructura de las URL entrantes. Si la URL no contiene ningún sufijo y no existe ninguna versión cacheada de la página disponible (el Capítulo 12 detalla el sistema de cache), la petición se redirige al script index.php.

Truco Para poder utilizar puntos en las rutas, es necesario comentar las dos primeras condiciones de reescritura (RewriteCond) y la primera regla de reescritura (RewriteRule) en el archivo .htaccess

No obstante, el directorio web/ de un proyecto Symfony lo comparten todas las aplicaciones y todos los entornos de ejecución del proyecto. Por este motivo, es habitual que exista más de un controlador frontal en el directorio web. Por ejemplo, si un proyecto tiene dos aplicaciones llamadas frontend y backend y dos entornos de ejecución llamados dev y prod, el directorio web/ contiene 4 controladores frontales:

index.php         // frontend en prod
frontend_dev.php  // frontend en dev
backend.php       // backend en prod
backend_dev.php   // backend en dev

Las opciones de mod_rewrite solo permiten especificar un script por defecto. Si se establece el valor on a la opción no_script_name de todas las aplicaciones y todos los entornos, todas las URL se interpretan como si fueran peticiones al controlador frontal de la aplicación frontend en el entorno de producción (prod). Esta es la razón por la que en un mismo proyecto, solo se pueden aprovechar del sistema de enrutamiento una aplicación y un entorno de ejecución concretos.

Truco Existe una forma de acceder a más de una aplicación sin indicar el nombre del script. Para ello, se crean subdirectorios en el directorio web/ y se mueven los controladores frontales a cada subdirectorio. Después, se modifica el valor de las constantes SF_ROOT_DIR para cada uno de ellos y se crea el archivo .htaccess de configuración para cada aplicación.