Restricciones en URLs en Symfony

Se pueden añadir restricciones en los parámetros de las URLs de los requests en una aplicación Symfony

Contenido modificable

Si ves errores o quieres modificar/añadir contenidos, puedes crear un pull request. Gracias

Tenemos dos controllers en la clase BlogController:

// src/AppBundle/Controller/BlogController.php

// ...
class BlogController extends Controller
{
    /**
     * @Route("/blog/{page}", defaults={"page" = 1})
     */
    public function indexAction($page)
    {
        // ...
    }

    /**
     * @Route("/blog/{slug}")
     */
    public function showAction($slug)
    {
        // ...
    }
}

Ambas routes tienen patrones que hacen coincidir URLs como /blog/*. El routing de Symfony siempre hará coincidir la primera route que encuentre. La route blog_show nunca coincidirá. Una URL como /blog/my-blog-post coincidirá con la primera route y devolverá un valor my-blog-post al parámetro {page}.

Para solucionar esto podemos añadir restricciones a las routes. Las routes en este ejemplo funcionarán perfectamente si el placeholder de /blog/{page} sólo coincidiera con integers. Restricciones con expresiones regulares pueden añadirse en cada parámetro:

// src/AppBundle/Controller/BlogController.php

// ...

/**
 * @Route("/blog/{page}", defaults={"page": 1}, requirements={
 *     "page": "\d+"
 * })
 */
public function indexAction($page)
{
    // ...
}

El requisito \d+ es una expresión regular que indica que el valor del parámetro {page} debe ser un número. Ahora una route como my-blog-post sólo coincidirá con la segunda route /blog/{slug}.

El orden de las routes es muy importante. Si se cambiara el orden en que están definidas las routes anteriores, la URL /blog/2 coincidiría con /blog/{slug} y nunca llegaría a /blog/{page}. Con un orden aduecuado y el uso de restricciones se puede conseguir lo que se quiera.

Ya que los requisitos están descritos con expresiones regulares, la complejidad y flexibilidad de cada requisitio depende de ti. Suponemos que la homepage de una aplicación está disponible en dos idiomas diferentes, basándose en la URL:

// src/AppBundle/Controller/MainController.php

// ...
class MainController extends Controller
{
    /**
     * @Route("/{_locale}", defaults={"_locale": "en"}, requirements={
     *     "_locale": "en|fr"
     * })
     */
    public function homepageAction($_locale)
    {
    }
}

La aplicación responderá con esta route si se trata de en o fr. Si se intenta con es no responderá esta route.