Le composant router de symfony permet de solliciter la méthode d'un contrôleur, en lui passant éventuellement des paramètres, en fonction de l'url demandée.
Les routes peuvent être définies par l'intermédiaire :
La méthode la plus souple est l'utilisation d'annotations. Elle nécessite l'installation du composant annotations :
composer require annotations
Création de routes avec l'annotation @Route
namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Routing\Annotation\Route; class BlogController extends Controller { /** * Matches /blog exactly * * @Route("/blog", name="blog_list") */ public function list() { // ... } /** * Matches /blog/* * * @Route("/blog/{slug}", name="blog_show") */ public function show($slug) { // $slug will equal the dynamic part of the URL // e.g. at /blog/yay-routing, then $slug='yay-routing' // ... } }
Dans la console, la commande suivante liste les routes existantes :
php bin/console debug:router
Les paramètres de routes sont passés à l'aide des accolades :
namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Routing\Annotation\Route; class BlogController extends Controller { /** * @Route("/blog/{page}", name="blog_list") */ public function list($page) { // ... } /** * @Route("/blog/{slug}", name="blog_show") */ public function show($slug) { // ... } }
Dans l'exemple précédent, les 2 routes sont en conflit, puisqu'elles correspondent toutes les 2 à une url du type /blog/*.
Le router choisira toujours dans ce cas la première correspondance trouvée : la route blog_list, ce qui est problématique.
Il est possible d'affiner ce routage, en précisant pour la route blog_list que le paramètre page doit être un entier :
On ajoute dans ce cas un “requirement”, correspondant à une expression régulière :
namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Routing\Annotation\Route; class BlogController extends Controller { /** * @Route("/blog/{page}", name="blog_list", requirements={"page"="\d+"}) */ public function list($page) { // ... } // ... }
Il est possible de donner à un paramètre une valeur par défaut :
namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Routing\Annotation\Route; class BlogController extends Controller { /** * @Route("/blog/{page}", name="blog_list", requirements={"page"="\d+"}) */ public function list($page = 1) { // ... } }
L'ajout de l'attribut methods à la route permet de spécifier la/les méthode(s) utilisables :
namespace App\Controller; // ... class BlogApiController extends Controller { /** * @Route("/api/posts/{id}", methods={"GET","HEAD"}) */ public function show($id) { // ... return a JSON response with the post } /** * @Route("/api/posts/{id}", methods="PUT") */ public function edit($id) { // ... edit a post } }
4 paramètres spéciaux sont utilisable au niveau des routes :
_controller | Permet de spécifier le contrôleur à exécuter quand la route est sollicitée. |
---|---|
_format | Utilisé pour définir le format de la requête (html, json…) voir format param. |
_fragment | Utilisé pour définir le fragment après le # dans le cas d'une url interne à la page |
_locale | Utilisé pour définir la “locale” de la requête (fr/en…) voir locale |
Exemple :
// ... class ArticleController extends Controller { /** * @Route( * "/articles/{_locale}/{year}/{slug}.{_format}", * defaults={"_format": "html"}, * requirements={ * "_locale": "en|fr", * "_format": "html|rss", * "year": "\d+" * } * ) */ public function show($_locale, $year, $slug) { } }
class MainController extends Controller { public function show($slug) { // ... // /blog/my-blog-post $url = $this->generateUrl( 'blog_show', array('slug' => 'my-blog-post') ); } }
Les variables supplémentaires sont ajoutées en tant que query string :
$this->generateUrl('blog_list', array( 'page' => 2, 'category' => 'Symfony', )); // /blog/2?category=Symfony
Il est nécessaire d'injecter une instance de UrlGeneratorInterface
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class SomeService { private $router; public function __construct(UrlGeneratorInterface $router) { $this->router = $router; } public function someMethod() { $url = $this->router->generate( 'blog_show', array('slug' => 'my-blog-post') ); // ... } }