Symfony 1.2, la guía definitiva

9.3. Helpers de enlaces

Debido al sistema de enrutamiento, es conveniente utilizar los helpers de enlaces en las plantillas en vez de etiquetas <a> normales y corrientes. Más que una molestia, el uso de estos helpers debe verse como un método sencillo de mantener la aplicación limpia y muy fácil de mantener. Además, los helpers de enlaces incluyen una serie de utilidades y atajos que no es recomendable desaprovechar.

9.3.1. Hiperenlaces, botones y formularios

En secciones anteriores ya se ha mostrado el helper link_to(). Se utiliza para mostrar enlaces válidos según XHTML y requiere de 2 parámetros: el elemento que va a mostrar el enlace y la URI interna del recurso al que apunta el enlace. Si en vez de un enlace se necesita un botón, simplemente se utiliza el helper button_to(). Los formularios también disponen de un helper para controlar el valor del atributo action. El siguiente capítulo explica los formularios en detalle. El listado 9-7 muestra algunos ejemplos de helpers de enlaces.

Listado 9-7 - Helpers de enlaces para las etiquetas <a>, <input> y <form>

// Enlace simple de texto
<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia">Mi artículo</a>

// Enlace en una imagen
<?php echo link_to(image_tag('ver.gif'), 'articulo/ver?titulo=Economia_en_Francia') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia"><img src="/images/ver.gif" /></a>

// Boton
<?php echo button_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
 => <input value="Mi artículo" type="button" onclick="document.location.href='/url/con/enrutamiento/a/Economia_en_Francia';" />

// Formulario
<?php echo form_tag('articulo/ver?titulo=Economia_en_Francia') ?>
 => <form method="post" action="/url/con/enrutamiento/a/Economia_en_Francia" />

Los helpers de enlaces aceptan URI internas y también URL absolutas (las que empiezan por http:// y para las que no se aplica el sistema de enrutamiento) y URL internas a una página (también llamadas anclas). Las aplicaciones reales suelen construir sus URI internas en base a una serie de parámetros dinámicos. El listado 9-8 muestra ejemplos de todos estos casos.

Listado 9-8 - URL que admiten los helpers de enlaces

// URI interna
<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia">Mi artículo</a>

// URI interna con parámetros dinámicos
<?php echo link_to('Mi artículo', 'articulo/ver?titulo='.$articulo->getTitulo()) ?>

// URI interna con anclas (enlaces a secciones internas de la página)
<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia#seccion1') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia#seccion1">Mi artículo</a>

// URL absolutas
<?php echo link_to('Mi artículo', 'http://www.ejemplo.com/cualquierpagina.html') ?>
 => <a href="http://www.ejemplo.com/cualquierpagina.html">Mi artículo</a>

9.3.2. Opciones de los helpers de enlaces

Como se explicó en el Capítulo 7, los helpers aceptan como argumento opciones adicionales, que se pueden indicar en forma de array asociativo o en forma de cadena de texto. Los helpers de enlaces también aceptan este tipo de opciones, como muestra el listado 9-9.

Listado 9-9 - Los helpers de enlaces aceptan opciones adicionales

// Opciones adicionales como array asociativo
<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia', array(
  'class'  => 'miclasecss',
  'target' => '_blank'
)) ?>

// Opciones adicionales como cadena de texto (producen el mismo resultado)
<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia','class=miclasecss target=_blank') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia" class="miclasecss" target="_blank">Mi artículo</a>

También se pueden utilizar otras opciones específicas de Symfony llamadas confirm y popup. La primera muestra una ventana JavaScript de confirmación al pinchar en el enlace y la segunda opción abre el destino del enlace en una nueva ventana, como se muestra en el listado 9-10.

Listado 9-10 - Opciones confirm y popup en los helpers de enlaces

<?php echo link_to('Borrar elemento', 'item/borrar?id=123', 'confirm=¿Estás seguro?') ?>
 => <a onclick="return confirm('¿Estás seguro?');"
       href="/url/con/enrutamiento/a/borrar/123.html">Borrar elemento</a>

<?php echo link_to('Añadir al carrito', 'carritoCompra/anadir?id=100', 'popup=true') ?>
 => <a onclick="window.open(this.href);return false;"
       href="/url/con/enrutamiento/a/carritoCompra/anadir/id/100.html">Añadir al carrito</a>

<?php echo link_to('Añadir al carrito', 'carritoCompra/anadir?id=100', array(
  'popup' => array('popupWindow', 'width=310,height=400,left=320,top=0')
)) ?>
 => <a onclick="window.open(this.href,'popupWindow','width=310,height=400,left=320,top=0');return false;"
       href="/url/con/enrutamiento/a/carritoCompra/anadir/id/100.html">Añadir al carrito</a>

Estas opciones también se pueden combinar entre si.

9.3.3. Opciones GET y POST falsas

En ocasiones, los programadores web utilizan peticiones GET para realizar acciones más propias de una petición POST. Si se considera por ejemplo la siguiente URL:

http://www.ejemplo.com/index.php/carritoCompra/anadir/id/100

Este tipo de petición modifica los datos de la aplicación, ya que añade un elemento al objeto que representa el carrito de la compra y que se almacena en la sesión del servidor o en una base de datos. Si los usuarios añaden esta URL a los favoritos de sus navegadores o si la URL se cachea o es indexada por un buscador, se pueden producir problemas en la base de datos y en las métricas del sitio web. En realidad, esta petición debería tratarse como una petición de tipo POST, ya que los robots que utilizan los buscadores no hacen peticiones POST para indexar las páginas.

Symfony permite transformar una llamada a los helpers link_to() o button_to() en una petición POST. Solamente es necesario añadir la opción post=true, tal y como se muestra en el listado 9-11.

Listado 9-11 - Convirtiendo un enlace en una petición POST

<?php echo link_to('Ver carrito de la compra', 'carritoCompra/anadir?id=100', 'post=true') ?>
 => <a onclick="f = document.createElement('form'); document.body.appendChild(f);
                f.method = 'POST'; f.action = this.href; f.submit();return false;"
       href="/carritoCompra/anadir/id/100.html">Ver carrito de la compra</a>

La etiqueta <a> resultante conserva el atributo href, por lo que los navegadores sin soporte de JavaScript, como por ejemplo los robots que utilizan los buscadores, utilizan el enlace normal con la petición GET. Asi que es posible que se deba restringir la acción para que solamente responda a las peticiones de tipo POST, que se puede realizar añadiendo por ejemplo la siguiente instrucción al principio de la acción:

$this->forward404Unless($this->getRequest()->isMethod('post'));

Esta opción no se debe utilizar en los enlaces que se encuentran dentro de los formularios, ya que genera su propia etiqueta <form>.

Se trata de una buena práctica definir como peticiones POST los enlaces que realizan acciones que modifican los datos.

9.3.4. Forzando los parámetros de la petición como variables de tipo GET

Las variables que se pasan como parámetro a link_to() se transforman en patrones según las reglas del sistema de enrutamiento. Si no existe en el archivo routing.yml ninguna regla que coincida con la URI interna, se aplica la regla por defecto que transforma modulo/accion?clave=valor en /modulo/accion/clave/valor, como se muestra en el listado 9-12.

Listado 9-12 - Regla de enrutamiento por defecto

<?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
=> <a href="/articulo/ver/titulo/Economia_en_Francia">Mi artículo</a>

Si quieres utilizar la sintaxis de las peticiones GET (para pasar los parámetros de la petición en la forma ?clave=valor) se deben indicar los parámetros en la opción query_string.

Si se utilizan enlaces que tienen una parte correspondiente a las anclas se pueden producir conflictos. Por ello, el nombre del ancla se debe indicar en la opción anchor en vez de añadirlo directamente a la URL. Todos los helpers de enlaces aceptan estas opciones, tal y como se muestra en el listado 9-13.

Listado 9-13 - Forzando el uso de variables tipo GET con la opción query_string

<?php echo link_to('Mi artículo', 'articulo/ver', array(
  'query_string' => 'titulo=Economia_en_Francia',
  'anchor' => 'seccion_dentro_de_la_pagina'
)) ?>
=> <a href="/articulo/ver?titulo=Economia_en_Francia#seccion_dentro_de_la_pagina">Mi artículo</a>

Las URL con los parámetros en forma de variables GET se pueden interpretar por los scripts en el lado del cliente y por las variables $_GET y $_REQUEST en el lado del servidor.

9.3.5. Utilizando rutas absolutas

Los helpers de enlaces y de contenidos estáticos generan rutas relativas por defecto. Para forzar el uso de rutas absolutas, se debe asignar el valor true a la opción absolute, como muestra el listado 9-14. Esta técnica es muy útil cuando se deben incluir enlaces en mensajes de email, canales RSS o respuestas de una API.

Listado 9-14 - Utilizando URL absolutas en vez de relativas

<?php echo url_for('articulo/ver?titulo=Economia_en_Francia') ?>
 => '/url/con/enrutamiento/a/Economia_en_Francia'
<?php echo url_for('articulo/ver?titulo=Economia_en_Francia', true) ?>
 => 'http://www.ejemplo.com/url/con/enrutamiento/a/Economia_en_Francia'

<?php echo link_to('economía', 'articulo/ver?titulo=Economia_en_Francia') ?>
 => <a href="/url/con/enrutamiento/a/Economia_en_Francia">economía</a>
<?php echo link_to('economía', 'articulo/ver?titulo=Economia_en_Francia','absolute=true') ?>
 => <a href=" http://www.ejemplo.com/url/con/enrutamiento/a/Economia_en_Francia">economía</a>

// Lo mismo sucede con los helpers de contenidos estáticos
<?php echo image_tag('prueba', 'absolute=true') ?>
<?php echo javascript_include_tag('miscript', 'absolute=true') ?>