La anotación @ParamConverter llama a converters para convertir parámetros de la petición a objetos. Estos objetos se almacenan como atributos de la petición y por lo tanto se pueden inyectar en los argumentos del método controlador:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* @Route("/blog/{id}")
* @ParamConverter("post", class="SensioBlogBundle:Post")
*/
public function showAction(Post $post)
{
}
Suceden varias cosas bajo el capó:
Si utilizas el tipo como el del ejemplo anterior, incluso puedes omitir la anotación @ParamConverter por completo:
// automático con firma de método
public function showAction(Post $post)
{
}
Para detectar qué convertidor está corrido en un parámetro se ejecuta el siguiente proceso :
El paquete tiene dos convertidor integrados, uno es el convertidor Doctrine y el otro``DateTime``.
Nombre de convertidor: doctrine.orm
El convertidor de Doctrine intenta convertir los atributos de la petición a entidades de recuperadas de la base de datos por Doctrine. Hay dos distintos posibles enfoques:
El siguiente algoritmo determina qué operación realizar.
De manera predeterminada, el convertidor de Doctrine utiliza el valor predeterminado del gestor de la entidad. Lo puedes configurar con la opción entity_manager:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* @Route("/blog/{id}")
* @ParamConverter("post", class="SensioBlogBundle:Post", options={"entity_manager" = "foo"})
*/
public function showAction(Post $post)
{
}
Si el marcador de posición no tiene el mismo nombre como clave primaria, pasa la opción id:
/**
* @Route("/blog/{post_id}")
* @ParamConverter("post", class="SensioBlogBundle:Post", options={"id" = "post_id"})
*/
public function showAction(Post $post)
{
}
Esto también te permite tener múltiples convertidores en una acción:
/**
* @Route("/blog/{id}/comments/{comment_id}")
* @ParamConverter("comment", class="SensioBlogBundle:Comment", options={"id" = "comment_id"})
*/
public function showAction(Post $post, Comment $comment)
{
}
En el ejemplo anterior, el argumento post es manejado automáticamente, pero el comentario está configurado con la anotación debido a que ambos no pueden seguir la convención predefinida.
Si quieres emparejar una entidad usando múltiples campos usa mapping:
/**
* @Route("/blog/{date}/{slug}/comments/{comment_slug}")
* @ParamConverter("post", options={"mapping": {"date": "date", "slug": "slug"}})
* @ParamConverter("comment", options={"mapping": {"comment_slug": "slug"}})
*/
public function showAction(Post $post, Comment $comment)
{
}
Si estás emparejando una entidad que utiliza varios campos, pero quieres excluir un argumento de la ruta para que forme parte de los criterios:
/**
* @Route("/blog/{date}/{slug}")
* @ParamConverter("post", options={"exclude": ["date"]})
*/
public function showAction(Post $post, \DateTime $date)
{
}
Si quieres especificar el método repository a utilizar para encontrar la entidad (por ejemplo, para añadir una unión a la consulta), puedes añadir la opción repository_method:
/**
* @Route("/blog/{id}")
* @ParamConverter("post", class="SensioBlogBundle:Post", options={"repository_method" = "findWithJoins"})
*/
public function showAction(Post $post)
{
}
Nombre de convertidor: datetime
El convertidor datetime convierte cualquier ruta o atributo de petición a una instancia de datetime:
/**
* @Route("/blog/archive/{start}/{end}")
*/
public function archiveAction(\DateTime $start, \DateTime $end)
{
}
Por omisión puede analizar cualquier formato de fecha aceptado por el constructor de DateTime. Puedes ser más estricto con la entrada dada a través de las opciones:
/**
* @Route("/blog/archive/{start}/{end}")
* @ParamConverter("start", options={"format": "Y-m-d"})
* @ParamConverter("end", options={"format": "Y-m-d"})
*/
public function archiveAction(\DateTime $start, \DateTime $end)
{
}
Todos los convertidores deben implementar la Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface:
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Symfony\Component\HttpFoundation\Request;
interface ParamConverterInterface
{
function apply(Request $request, ConfigurationInterface $configuration);
function supports(ConfigurationInterface $configuration);
}
El método supports() debe devolver true cuando sea capaz de convertir la configuración dada (una instancia de ParamConverter).
La instancia de ParamConverter tiene tres piezas de información sobre la anotación:
El método apply() se llama cuando una configuración es compatible. Basándonos en los atributos de la petición, debemos establecer un atributo llamado $configuration->getName(), que almacene un objeto de la clase $configuration->getClass().
Para registrar tu servicio convertidor tienes que añadir una etiqueta a tu servicio:
<service id="my_converter" class="MyBundle/Request/ParamConverter/MyConverter">
<tag name="request.param_converter" priority="-2" converter="my_converter" />
</service>
Puedes registrar un convertidor por prioridad, por nombre (atributo «converter») o ambos. Si no especificas una prioridad o nombre el convertidor será añadido a la pila de convertidores con una prioridad de 0. Para desactiva explícitamente la inscripción por prioridad tienes que ajustar la priority="false" en la definición de tu etiqueta.
Truco
Utiliza la clase DoctrineParamConverter como plantilla para tus propios convertidores.