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 ejemploadmin.php
? En resumen, las URL directas permiten jugar con ellas de forma que se complica el control de 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
- 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/2010/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.
- Su implementación técnica se oculta a los usuarios: no es posible conocer el script que se utiliza y no pueden jugar a cambiar el valor de parámetros como el
id
, por lo que tu aplicación es menos vulnerable. Además, puedes cambiar todo el funcionamiento interno de tu aplicación sin que afecte a las URL, por lo que no se producirán errores de tipo404
y tampoco tendrás que hacer redirecciones permanentes.
- 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][¶metro2=valor2][¶metro3=valor3]... // Ejemplo de URI interna que nunca se muestra al usuario articulo/permalink?ano=2010&tema=economia&titulo=sectores-actividad // Ejemplo de URL externa que se muestra al usuario http://www.ejemplo.com/articulos/economia/2010/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/2010/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' => '2010' 'titulo' => 'sectores-actividad'
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=2010&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/2010/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=2010&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/2010/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.