Symfony 1.2, la guía definitiva

9.1. ¿Qué es el enrutamiento?

El enrutamiento es un mecanismo que reescribe las URL para simplificar su aspecto. Antes de poder comprender su importancia, es necesario dedicar unos minutos al estudio de las URL de las aplicaciones

9.1.1. URL como instrucciones de servidor

Cuando el usuario realiza una acción, las URL se encargan de enviar la información desde el navegador hasta el servidor. Las URL tradicionales incluyen la ruta hasta el script del servidor y algunos parámetros necesarios para completar la petición, como se muestra en el siguiente ejemplo:

http://www.ejemplo.com/web/controlador/articulo.php?id=123456&codigo_formato=6532

La URL anterior incluye información sobre la arquitectura de la aplicación y sobre su base de datos. Normalmente, los programadores evitan mostrar la estructura interna de la aplicación en la interfaz (las páginas por ejemplo se titulan "Perfil personal" y no "QZ7.65"). Desvelar detalles internos de la aplicación en la URL no solo contradice esta norma, sino que tiene otras desventajas:

  • Los datos técnicos que se muestran en las URL son una fuente potencial de agujeros de seguridad. En el ejemplo anterior, ¿qué sucede si un usuario malicioso modifica el valor del parámetro id? ¿Supone este caso que la aplicación ofrece una interfaz directa a la base de datos? ¿Qué sucedería si otro usuario probara otros nombres de script, como por ejemplo admin.php? En resumen, las URL directas permiten jugar de forma directa y sencilla con una aplicación y es casi imposible manejar su seguridad.
  • Las URL complejas son muy difíciles de leer y hoy en día las URL no solo aparecen en la barra de direcciones. También suelen aparecer cuando un usuario pasa el ratón por encima de un enlace y también en los resultados de búsqueda. Cuando los usuarios buscan información, es más útil proporcionarles URL sencillas y fáciles de entender y no URL complejas como las que se muestran en la figura 9.1
Las URL aparecen en muchos lugares, como por ejemplo los resultados de búsqueda

Figura 9.1 Las URL aparecen en muchos lugares, como por ejemplo los resultados de búsqueda

  • Si se modifica una URL (porque cambia el nombre del script o el de alguno de sus parámetros), se deben modificar todos los enlaces a esa URL. De esta forma, las modificaciones en la estructura del controlador son muy pesadas y costosas, lo que contradice la filosofía del desarrollo ágil de aplicaciones.

La situación podría ser incluso mucho peor si Symfony no utilizara un controlador frontal; es decir, si la aplicación contiene varios scripts accesibles desde el exterior, como por ejemplo:

http://www.ejemplo.com/web/galeria/album.php?nombre=mis%20vacaciones
http://www.ejemplo.com/web/weblog/publico/post/listado.php
http://www.ejemplo.com/web/general/contenido/pagina.php?nombre=sobre%20nosotros

En este caso, los programadores deben hacer coincidir la estructura de las URL y la estructura del sistema de archivos, por lo que su mantenimiento se convierte en una pesadilla cuando cualquiera de las dos estructuras se modifica.

9.1.2. URL como parte de la interfaz

Una de las ideas del sistema de enrutamiento es utilizar las URL como parte de la interfaz. Las aplicaciones trasladan información al usuario mediante el formateo de las URL y el usuario puede utilizar las URL para acceder a los recursos de la aplicación.

Lo anterior es posible en las aplicaciones Symfony porque la URL que se muestra al usuario no tiene que guardar obligatoriamente relación con la instrucción del servidor necesaria para completar la petición. En su lugar, la URL está relacionada con el recurso solicitado, y su aspecto puede configurarse libremente. En Symfony es posible por ejemplo utilizar la siguiente URL y obtener los mismos resultados que la primera URL mostrada en este capítulo:

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

Este tipo de URL tiene muchas ventajas:

  • Las URL tienen significado y ayudan a los usuarios a decidir si la página que se cargará al pulsar sobre un enlace contiene lo que esperan. Un enlace puede contener detalles adicionales sobre el recurso que enlaza. Esto último es especialmente útil para los resultados de los buscadores. Además, muchas veces las URL aparecen sin que se mencione el título de su página (por ejemplo cuando se copian las URL en un mensaje de email) por lo que en ese caso deberían contener su propio significado. La figura 9-2 muestra una URL sencilla y fácil de entender.
Las URL pueden incluir información adicional sobre una página, como por ejemplo su fecha de publicación

Figura 9.2 Las URL pueden incluir información adicional sobre una página, como por ejemplo su fecha de publicación

  • Las URL que aparecen en los documentos impresos son más fáciles de escribir y de recordar. Si la dirección del sitio web de una empresa se muestra en una tarjeta de visita con un aspecto similar a http://www.ejemplo.com/controlador/web/index.jsp?id=ERD4, probablemente no reciba muchas visitas.
  • La URL se puede convertir en una especie de línea de comandos, que permita realizar acciones u obtener información de forma intuitiva. Este tipo de aplicaciones son las que más rápidamente utilizan los usuarios más avanzados.
// Listado de resultados: se puede añadir una nueva etiqueta para restringir los resultados
http://del.icio.us/tag/symfony+ajax
// Página de perfil de usuario: se puede modificar el nombre para obtener otro perfil
http://www.askeet.com/user/francois
  • Se puede modificar el aspecto de la URL y el del nombre de la acción o de los parámetros de forma independiente y con una sola modificación. En otras palabras, es posible empezar a programar la aplicación y después modificar el aspecto de las URL sin estropear completamente la aplicación.
  • Aunque se modifique la estructura interna de la aplicación, las URL pueden mantener su mismo aspecto hacia el exterior. De esta forma, las URL se convierten en persistentes y pueden ser añadidas a los marcadores o favoritos.
  • Cuando los motores de búsqueda indexan un sitio web, suelen tratar de forma diferente (incluso saltándoselas) a las páginas dinámicas (las que acaban en .php, .asp, etc.) Así que si se formatean las URL de esta forma, los buscadores creen que están indexando contenidos estáticos, por lo que generalmente se obtiene una mejor indexación de las páginas de la aplicación.
  • Son más seguras. Cualquier URL no reconocida se redirige a una página especificada por el programador y los usuarios no pueden navegar por el directorio raíz del servidor mediante la prueba de diferentes URL. La razón es que no se visualiza el nombre del script utilizado o el de sus parámetros.

La relación entre las URL mostradas al usuario y el nombre del script que se ejecuta y de sus parámetros está gestionada por el sistema de enrutamiento, que utiliza patrones que se pueden modificar mediante la configuración de la aplicación.

Nota ¿Qué sucede con los contenidos estáticos? Afortunadamente, las URL de los contenidos estáticos (imágenes, hojas de estilos y archivos de JavaScript) no suelen mostrarse durante la navegación, por lo que no es necesario utilizar el sistema de enrutamiento para este tipo de contenidos. Symfony almacena todos los contenidos estáticos en el directorio web/ y sus URL se corresponden con su localización en el sistema de archivos. No obstante, es posible gestionar dinámicamente los contenidos estáticos mediante URL generadas con un helper para contenidos estáticos. Por ejemplo, para mostrar una imagen generada dinámicamnete, se puede utilizar el helper image_tag(url_for('captcha/image?key='.$key)).

9.1.3. Cómo funciona

Symfony desasocia las URL externas y las URI utilizadas internamente. La correspondencia entre las dos es responsabilidad del sistema de enrutamiento. Symfony simplifica este mecanismo utilizando una sintaxis para las URI internas muy similar a la de las URL habituales. El listado 9-1 muestra un ejemplo.

Listado 9-1 - URL externas y URI internas

// Sintaxis de las URI internas
<modulo>/<accion>[?parametro1=valor1][&parametro2=valor2][&parametro3=valor3]...

// Ejemplo de URI interna que nunca se muestra al usuario
articulo/permalink?ano=2006&tema=economia&titulo=sectores-actividad

// Ejemplo de URL externa que se muestra al usuario
http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html

El sistema de enrutamiento utiliza un archivo de configuración especial, llamado routing.yml, en el que se pueden definir las reglas de enrutamiento. Si se considera la regla mostrada en el listado 9-2, se define un patrón cuyo aspecto es articulos/*/*/* y que también define el nombre de cada pieza que forma parte de la URL.

Listado 9-2 - Ejemplo de regla de enrutamiento

articulo_segun_titulo:
  url:    articulos/:tema/:ano/:titulo.html
  param:  { module: articulo, action: permalink }

Todas las peticiones realizadas a una aplicación Symfony son analizadas en primer lugar por el sistema de enrutamiento (que es muy sencillo porque todas las peticiones se gestionan mediante un único controlador frontal). El sistema de enrutamiento busca coincidencias entre la URL de la petición y los patrones definidos en las reglas de enrutamiento. Si se produce una coincidencia, las partes del patrón que tienen nombre se transforman en parámetros de la petición y se juntan a los parámetros definidos en la clave param:. El listado 9-3 muestra su funcionamiento.

Listado 9-3 - El sistema de enrutamiento interpreta las URL de las peticiones entrantes

// El usuario escribe (o pulsa) sobre esta URL externa
http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html

// El controlador frontal comprueba que coincide con la regla articulo_segun_titulo
// El sistema de enrutamiento crea los siguientes parámetros de la petición
  'module'  => 'articulo'
  'action'  => 'permalink'
  'tema'    => 'economia'
  'ano'     => '2006'
  'titulo'  => 'sectores-actividad'

Truco La extensión .html de las URL externas es solo un adorno y por ese motivo el sistema de enrutamiento la ignora. Su única función es la de hacer que las páginas dinámicas parezcan páginas estáticas. La sección "Configuración del enrutamiento" al final de este capítulo explica cómo activar esta extensión.

Después, la petición se pasa a la acción permalink del módulo articulo, que dispone de toda la información necesaria en los parámetros de la petición para obtener el artículo solicitado.

El mecanismo de enrutamiento también funciona en la otra dirección. Para mostrar las URL en los enlaces de una aplicación, se debe proporcionar al sistema de enrutamiento la información necesaria para determinar la regla que se debe aplicar a cada enlace. Además, no se deben escribir los enlaces directamente con etiquetas <a> (ya que de esta forma no se estaría utilizando el sistema de enrutamiento) sino con un helper especial, tal y como se muestra en el listado 9-4.

Listado 9-4 - El sistema de enrutamiento formatea las URL externas mostradas en las plantillas

// El helper url_for() transforma una URI interna en una URL externa
<a href="<?php echo url_for('articulo/permalink?tema=economia&ano=2006&titulo=sectores-actividad') ?>">pincha aquí</a>

// El helper reconoce que la URI cumple con la regla articulo_segun_titulo
// El sistema de enrutamiento crea una URL externa a partir de el
 => <a href="http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html">pincha aquí</a>

// El helper link_to() muestra directamente un enlace
// y evita tener que mezclar PHP y HTML
<?php echo link_to(
  'pincha aqui',
  'articulo/permalink?tema=economia&ano=2006&titulo=sectores-actividad'
) ?>

// Internamente link_to() llama a url_for(), por lo que el resultado es el mismo
 => <a href="http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html">pincha aquí</a>

De forma que el enrutamiento es un mecanismo bidireccional y solo funciona cuando se utiliza el helper link_to() para mostrar todos los enlaces.