Licence CC BY-NC-SA

Le routeur de Symfony2

Comme nous avons pu le voir, le rôle du routeur est, à partir d'une URL, de déterminer quel contrôleur appeler et avec quels arguments. Cela permet de configurer son application pour avoir de très belles URL, ce qui est important pour le référencement et même pour le confort des visiteurs. Soyons d'accord, l'URL /article/le-systeme-de-route est bien plus sexy que index.php?controlleur=article&methode=voir&id=5 !

Vous avez sans doute déjà entendu parler d'URL Rewriting ? Le routeur, bien que différent, permet effectivement de faire l'équivalent de l'URL Rewriting, mais il le fait côté PHP, et donc est bien mieux intégré à notre code.

Le fonctionnement

L'objectif de ce chapitre est de vous transmettre toutes les connaissances pour pouvoir créer ce que l'on appelle un fichier de mapping des routes (un fichier de correspondances, en français). Ce fichier, généralement situé dans votreBundle/Resources/config/routing.yml, contient la définition des routes. Chaque route fait la correspondance entre une URL et le contrôleur à appeler. Je vous invite à mettre dès maintenant les routes présentées au code suivant dans le fichier, nous allons travailler dessus dans ce chapitre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# src/sdz/BlogBundle/Resources/config/routing.yml

sdzblog_accueil:
    path:      /blog
    defaults:  { _controller: SdzBlogBundle:Blog:index }

sdzblog_voir:
    path:      /blog/article/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:voir }

sdzblog_ajouter:
    path:      /blog/ajouter
    defaults:  { _controller: SdzBlogBundle:Blog:ajouter }

Petit rappel au cas où : l'indentation se fait avec 4 espaces par niveau, et non avec des tabulations.

Vous pouvez supprimer la route helloTheWorld que nous avons créée au chapitre précédent, elle ne nous resservira plus. Vous pouvez voir qu'à la place nous avons maintenant une route sdzblog_accueil, qui pointe vers la même action du contrôleur. ;)

Fonctionnement du routeur

Dans le code précédent, vous pouvez distinguer trois blocs. Chacun correspond à une route. Nous les verrons en détail plus loin, mais vous pouvez constater que chaque route prend :

  • Une entrée (ligne path) : c'est l'URL à capturer ;
  • Une sortie (ligne defaults) : ce sont les paramètres de la route, notamment celui qui dit quel est le contrôleur à appeler.

Le but du routeur est donc, à partir d'une URL, de trouver la route correspondante et de retourner le contrôleur que veut cette route. Pour trouver la bonne route, le routeur va les parcourir une par une, dans l'ordre du fichier, et s'arrêter à la première route qui fonctionne. La figure suivante est un schéma équivalent au chapitre précédent, mais actualisé pour notre fichier de routes précédent.

Cheminement du routeur

Et voici en texte le fonctionnement, pas à pas :

  1. On appelle l'URL /blog/article/5.
  2. Le routeur essaie de faire correspondre cette URL avec le path de la première route. Ici, /blog/article/5 ne correspond pas du tout à /blog (ligne path de la première route).
  3. Le routeur passe donc à la route suivante. Il essaie de faire correspondre /blog/article/5 avec /blog/article/{id}. Nous le verrons plus loin, mais {id} est un paramètre, une sorte de joker « je prends tout ». Cette route correspond, car nous avons bien : - /blog/article (URL) = /blog/article (route) ;
    • 5 (URL) = {id} (route).
  4. Le routeur s'arrête donc, il a trouvé sa route.
  5. Il demande à la route : « Quel contrôleur souhaites-tu appeler, et avec quels paramètres ? », la route répond : « Je veux le contrôleur SdzBlogBundle:Blog:voir, avec le paramètre $id = 5. »
  6. Le routeur renvoie donc ces informations au Kernel (le noyau de Symfony2).
  7. Le noyau va exécuter le bon contrôleur !

Dans le cas où le routeur ne trouve aucune route correspondante, le noyau de Symfony2 va déclencher une erreur 404.

Pour chaque page, il est possible de visualiser toutes les routes que le routeur essaie une à une, et celle qu'il utilise finalement. C'est le Profiler qui s'occupe de tracer cela, accessible depuis la barre d'outils : cliquez sur le nom de la route dans la barre d'outils, « sdzblog_accueil » si vous êtes sur la page /blog. Ce lien vous amène dans l'onglet « Request » du Profiler, mais allez dans l'onglet « Routing » qui nous intéresse. Vous devriez obtenir la figure suivante.

Liste des routes enregistrées par le routeur

Vous pouvez voir qu'il y a déjà pas mal de routes définies alors que nous n'avons rien fait. Ces routes qui commencent par /_profiler/ sont les routes nécessaires au Profiler, dans lequel vous êtes. Eh oui, c'est un bundle également, le bundle WebProfilerBundle !

Convention pour le nom du contrôleur

Vous l'avez vu, lorsque l'on définit le contrôleur à appeler dans la route, il y a une convention à respecter : la même que pour appeler un template (nous l'avons vue au chapitre précédent). Un rappel ne fait pas de mal : lorsque vous écrivez « SdzBlogBundle:Blog:voir », vous avez trois informations :

  • « SdzBlogBundle » est le nom du bundle dans lequel aller chercher le contrôleur. En terme de fichier, cela signifie pour Symfony2 : « Va voir dans le répertoire de ce bundle. ». Dans notre cas, Symfony2 ira voir dans src/Sdz/BlogBundle.
  • « Blog » est le nom du contrôleur à ouvrir. En terme de fichier, cela correspond à controller/BlogController.php dans le répertoire du bundle. Dans notre cas, nous avons comme chemin absolu src/Sdz/BlogBundle/controller/BlogController.php.
  • « voir » est le nom de l'action à exécuter au sein du contrôleur. Attention, lorsque vous définissez cette méthode dans le contrôleur, vous devez la faire suivre du suffixe « Action », comme ceci : <?php public function voirAction().

Les routes de base

Créer une route

Étudions la première route plus en détail :

1
2
3
4
5
# src/Sdz/BlogBundle/config/Resources/routing.yml

sdzblog_accueil:
    path:      /blog
    defaults:  { _controller: SdzBlogBundle:Blog:index }

Ce bloc représente ce que l'on nomme une « route ». Elle est constituée au minimum de trois éléments :

  • sdzblog_accueil est le nom de la route. Il n'a aucune importance dans le travail du routeur, mais il interviendra lorsque l'on voudra générer des URL : eh oui, on n'écrira pas l'URL à la main, mais on fera appel au routeur pour qu'il fasse le travail à notre place ! Retenez donc pour l'instant qu'il faut qu'un nom soit unique et clair. On a donc préfixé les routes de « sdzblog » pour l'unicité entre bundles.
  • path: /blog est l'URL sur laquelle la route s'applique. Ici, « /blog » correspond à une URL absolue du type http://www.monsite.com/blog.
  • defaults:  { _controller: SdzBlogBundle:Blog:index } correspond au contrôleur à appeler.

Vous avez maintenant les bases pour créer une route simple !

Créer une route avec des paramètres

Reprenons la deuxième route de notre exemple :

1
2
3
4
5
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir:
    path:     /blog/article/{id}
    defaults: { _controller: SdzBlogBundle:Blog:voir }

Grâce au paramètre {id} dans le path de notre route, toutes les URL du type /blog/article/* seront gérées par cette route, par exemple : /blog/article/5 ou /blog/article/654, ou même /blog/article/sodfihsodfih (on n'a pas encore dit que {id} devait être un nombre, patience !). Par contre, l'URL /blog/article ne sera pas interceptée, car le paramètre {id} n'est pas renseigné. En effet, les paramètres sont par défaut obligatoires, nous verrons quand et comment les rendre facultatifs plus loin dans ce chapitre.

Mais si le routeur s’arrêtait là, il n'aurait aucun intérêt. Toute sa puissance réside dans le fait que ce paramètre {id} est accessible depuis votre contrôleur ! Si vous appelez l'URL /blog/article/5, alors depuis votre contrôleur vous aurez la variable $id (du nom du paramètre) qui aura pour valeur « 5 ». Je vous invite à créer la méthode correspondante dans le contrôleur :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
// src/Sdz/BlogBundle/Controller/BlogController.php

namespace Sdz\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class BlogController extends Controller
{
  // … ici la méthode indexAction() que l'on a déjà créée

  // La route fait appel à SdzBlogBundle:Blog:voir, on doit donc définir la méthode voirAction
  // On donne à cette méthode l'argument $id, pour correspondre au paramètre {id} de la route
  public function voirAction($id)
  {
    // $id vaut 5 si l'on a appelé l'URL /blog/article/5

    // Ici, on récupèrera depuis la base de données l'article correspondant à l'id $id
    // Puis on passera l'article à la vue pour qu'elle puisse l'afficher

    return new Response("Affichage de l'article d'id : ".$id.".");
  }
}

N'oubliez pas de tester votre code à l'adresse suivante : http://localhost/Symfony/web/app_dev.php/blog/article/5, et amusez-vous à changer la valeur du paramètre.

Vous pouvez bien sûr multiplier les paramètres au sein d'une même route. Ajoutez cette route juste après la route sdzblog_voir, pour l'exemple :

1
2
3
4
5
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir_slug:
    path:     /blog/{annee}/{slug}.{format}
    defaults: { _controller: SdzBlogBundle:Blog:voirSlug }

Cette route permet d'intercepter les URL suivantes : /blog/2011/mon-weekend.html ou /blog/2012/symfony.xml, etc. Et voici la méthode correspondante qu'on aurait côté contrôleur :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
// src/Sdz/BlogBundle/Controller/BlogController.php

namespace Sdz\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class BlogController extends Controller
{
  // … ici les méthodes indexAction() et voirAction() que l'on a déjà créées

  // On récupère tous les paramètres en arguments de la méthode
  public function voirSlugAction($slug, $annee, $format)
  {
    // Ici le contenu de la méthode
    return new Response("On pourrait afficher l'article correspondant au slug '".$slug."', créé en ".$annee." et au format ".$format.".");
  }
}

Notez que l'ordre des arguments dans la définition de la méthode voirSlugAction() n'a pas d'importance. La route fait la correspondance à partir du nom des variables utilisées, non à partir de leur ordre. C'est toujours bon à savoir !

Revenez à notre route et notez également le point entre les paramètres {slug} et {format} : vous pouvez en effet séparer vos paramètres soit avec le slash (« / »), soit avec le point (« . »). Veillez donc à ne pas utiliser de point dans le contenu de vos paramètres. Par exemple, pour notre paramètre {slug}, une URL /blog/2011/mon-weekend.etait.bien.html ne va pas correspondre à cette route, car :

  • {annee} = 2011 ;
  • {slug} = mon-weekend ;
  • {format} = etait ;
  • ? = bien ;
  • ? = html ;

La route attend des paramètres à mettre en face de ces dernières valeurs, et comme il n'y en a pas cette route dit : « Cette URL ne me correspond pas, passez à la route suivante. » Attention donc à ce petit détail. ;)

Les routes avancées

Créer une route avec des paramètres et leurs contraintes

Nous avons créé une route avec des paramètres, très bien. Mais si quelqu'un essaie d'atteindre l'URL /blog/oaisd/aouish.oasidh, eh bien, rien ne l'en empêche ! Et pourtant, « oaisd » n'est pas tellement une année valide ! La solution ? Les contraintes sur les paramètres. Reprenons notre dernière route sdzblog_voir_slug :

1
2
3
4
5
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir_slug:
    path:      /blog/{annee}/{slug}.{format}
    defaults:  { _controller: SdzBlogBundle:Blog:voirSlug }

Nous voulons ne récupérer que les bonnes URL où l'année vaut « 2010 » et non « oshidf », par exemple. Cette dernière devrait retourner une erreur 404 (page introuvable). Pour cela, il nous suffit qu'aucune route ne l'intercepte ; ainsi, le routeur arrivera à la fin du fichier sans aucune route correspondante et il déclenchera tout seul une erreur 404.

Comment faire pour que notre paramètre {annee} n'intercepte pas « oshidf » ? C'est très simple :

1
2
3
4
5
6
7
8
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir_slug:
    path:      /blog/{annee}/{slug}.{format}
    defaults:  { _controller: SdzBlogBundle:Blog:voirSlug }
    requirements:
        annee:  \d{4}
        format: html|xml

Nous avons ajouté la section requirements. Comme vous pouvez le voir, on utilise les expressions régulières pour déterminer les contraintes que doivent respecter les paramètres. Ici :

  • \d{4} veut dire « quatre chiffres à la suite ». L'URL /blog/sdff/mon-weekend.html ne sera donc pas interceptée. Vous l'avez reconnue, c'est une expression régulière. Vous pouvez utiliser n'importe laquelle, je vous invite à lire le cours correspondant de M@teo21.
  • html|xml signifie « soit HTML, soit XML ». L'URL /blog/2011/mon-weekend.rss ne sera donc pas interceptée.

N'hésitez surtout pas à faire les tests ! Cette route est opérationnelle, nous avons créé l'action correspondante dans le contrôleur. Essayez donc de bien comprendre quels paramètres sont valides, lesquels ne le sont pas. Vous pouvez également changer la section requirements.

Maintenant, nous souhaitons aller plus loin. En effet, si le « .xml » est utile pour récupérer l'article au format XML (pourquoi pas ?), le « .html » semble inutile : par défaut, le visiteur veut toujours du HTML. Il faut donc rendre le paramètre {format} facultatif.

Utiliser des paramètres facultatifs

Reprenons notre route et ajoutons-y la possibilité pour {format} de ne pas être renseigné :

1
2
3
4
5
6
7
8
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir_slug:
    path:      /blog/{annee}/{slug}.{format}
    defaults:  { _controller: SdzBlogBundle:Blog:voirSlug, format: html }
    requirements:
        annee:  \d{4}
        format: html|xml

Nous avons juste ajouté une valeur par défaut dans le tableau defaults : format: html. C'est aussi simple que cela ! Ainsi, l'URL /blog/2011/mon-weekend sera bien interceptée et le paramètre format sera mis à sa valeur par défaut, à savoir « html ». Au niveau du contrôleur, rien ne change : vous gardez l'argument $format comme avant et celui-ci vaudra « html », la valeur par défaut.

Utiliser des « paramètres système »

Prenons l'exemple de notre paramètre {format} : lorsqu'il vaut « xml », vous allez afficher du XML et devrez donc envoyer le header avec le bon Content-type. Les développeurs de Symfony2 ont pensé à nous et prévu des « paramètres système ». Ils s'utilisent exactement comme des paramètres classiques, mais effectuent automatiquement des actions supplémentaires :

  • Le paramètre {_format} : lorsqu'il est utilisé (comme notre paramètre {format}, ajoutez juste un underscore), alors un header avec le Content-type correspondant est envoyé. Exemple : vous appelez /blog/2011/mon-weekend.xml et le routeur va dire à l'objet Request que l'utilisateur demande du XML. Ainsi, l'objet Response enverra un header Content-type: application/xml. Vous n'avez plus à vous en soucier ! Depuis le contrôleur, vous pouvez récupérer ce format soit avec l'argument $_format comme n'importe quel autre argument, soit via la méthode getRequestFormat() de l'objet Request. Par exemple : <?php $this->get('request')->getRequestFormat().
  • Le paramètre {_locale} : lorsqu'il est utilisé, il va définir la langue dans laquelle l'utilisateur souhaite obtenir la page. Ainsi, si vous avez défini des fichiers de traduction ou si vous employez des bundles qui en utilisent, alors les traductions dans la langue du paramètre {_locale} seront chargées. Pensez à mettre un requirements: sur la valeur de ce paramètre pour éviter que vos utilisateurs ne demandent le russe alors que votre site n'est que bilingue français-anglais.

Ajouter un préfixe lors de l'import de nos routes

Vous avez remarqué que nous avons mis /blog au début du path de chacune de nos routes. En effet, on crée un blog, on aimerait donc que toutes les URL aient ce préfixe /blog. Au lieu de les répéter à chaque fois, Symfony2 vous propose de rajouter un préfixe lors de l'import du fichier de notre bundle.

Modifiez donc le fichier app/config/routing.yml comme suit :

1
2
3
4
5
# app/config/routing.yml

SdzBlogBundle:
    resource:  "@SdzBlogBundle/Resources/config/routing.yml"
    prefix:    /blog

Vous pouvez ainsi enlever la partie /blog de chacune de vos routes. Bonus : si un jour vous souhaitez changer /blog par /blogdemichel, vous n'aurez qu'à modifier une seule ligne. ;)

Générer des URL

Pourquoi générer des URL ?

J'ai mentionné précédemment que le routeur pouvait aussi générer des URL à partir du nom des routes. En effet, vu que le routeur a toutes les routes à sa disposition, il est capable d'associer une route à une certaine URL, mais également de reconstruire l'URL correspondant à une certaine route. Ce n'est pas une fonctionnalité annexe, mais bien un outil puissant que nous avons là !

Par exemple, nous avons une route nommée « sdzblog_voir » qui écoute l'URL /blog/article/{id}. Vous décidez un jour de raccourcir vos URL et vous aimeriez bien que vos articles soient disponibles depuis /blog/a/{id}. Si vous aviez écrit toutes vos URL à la main, vous auriez dû toutes les changer à la main, une par une. Grâce à la génération d'URL, vous ne modifiez que la route : ainsi, toutes les URL générées seront mises à jour ! C'est un exemple simple, mais vous pouvez trouver des cas bien réels et tout aussi gênants sans la génération d'URL.

Comment générer des URL ?

1. Depuis le contrôleur

Pour générer une URL, vous devez le demander au routeur en lui donnant deux arguments : le nom de la route ainsi que les éventuels paramètres de cette route.

Depuis un contrôleur, c'est la méthode <?php $this->generateUrl() qu'il faut appeler. Par exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// src/Sdz/BlogBundle/Controller/BlogController.php

namespace Sdz\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class BlogController extends Controller
{
  public function indexAction()
  {
    // On fixe un id au hasard ici, il sera dynamique par la suite, évidemment
    $id = 5;

    // On veut avoir l'URL de l'article d'id $id.
    $url = $this->generateUrl('sdzblog_voir', array('id' => $id));
    // $url vaut « /blog/article/5 »

    // On redirige vers cette URL (ça ne sert à rien, on est d'accord, c'est pour l'exemple !)
    return $this->redirect($url);
  }
}

Pour générer une URL absolue, lorsque vous l'envoyez par e-mail, par exemple, il faut mettre le troisième argument à true. Exemple :

1
2
<?php
$url = $this->generateUrl('sdzblog_voir', array('id' => $id), true);

Ainsi, $url vaut http://monsite.com/blog/article/5 et pas uniquement /blog/article/5.

2. Depuis une vue Twig

Vous aurez bien plus l'occasion de devoir générer une URL depuis la vue. C'est la fonction path qu'il faut utiliser depuis un template Twig :

1
2
3
{# Dans une vue Twig, en considérant bien sûr que la variable article_id est disponible #}

<a href="{{ path('sdzblog_voir', { 'id': article_id }) }}">Lien vers l'article d'id {{ article_id }}</a>

Et pour générer une URL absolue depuis Twig, pas de troisième argument, mais on utilise la fonction url() au lieu de path(). Elle s'utilise exactement de la même manière, seul le nom change.

Voilà : vous savez générer des URL, ce n'était vraiment pas compliqué. Pensez bien à utiliser la fonction {{ path }} pour tous vos liens dans vos templates. :)

Application : les routes de notre blog

Construction des routes

Revenons à notre blog. Maintenant que nous savons créer des routes, je vous propose de faire un premier jet de ce que seront nos URL. Voici les routes que je vous propose de créer, libre à vous d'en changer.

Page d'accueil

On souhaite avoir une URL très simple pour la page d'accueil : /blog. Comme /blog est défini comme préfixe lors du chargement des routes de notre bundle, le path ici est « / ». Mais on veut aussi pouvoir parcourir les articles plus anciens, donc il nous faut une notion de page courante. En ajoutant le paramètre facultatif {page}, nous aurons :

/blog

page = 1

/blog/1

page = 1

/blog/2

page = 2

C'est plutôt joli, non ? Voici la route :

1
2
3
4
5
6
7
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_accueil:
    path:      /{page}
    defaults:  { _controller: SdzBlogBundle:Blog:index, page: 1 }
    requirements:
        page:  \d*

Page de visualisation d'un article

Pour la page d'un unique article, la route est très simple. Il suffit juste de bien mettre un paramètre {id} qui nous servira à récupérer le bon article côté contrôleur. Voici la route :

1
2
3
4
5
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir:
    path:      /article/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:voir }

Ajout, modification et suppression

Les routes sont simples :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_ajouter:
    path:      /ajouter
    defaults:  { _controller: SdzBlogBundle:Blog:ajouter }

sdzblog_modifier:
    path:      /modifier/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:modifier }
    requirements:
        id:  \d+

sdzblog_supprimer:
    path:      /supprimer/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:supprimer }
    requirements:
        id:  \d+

Récapitulatif

Voici le code complet de notre fichier src/Sdz/BlogBundle/Resources/config/routing.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_accueil:
    path:      /{page}
    defaults:  { _controller: SdzBlogBundle:Blog:index, page: 1 }
    requirements:
        page:  \d*

sdzblog_voir:
    path:      /article/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:voir }
    requirements:
        id:  \d+

sdzblog_ajouter:
    path:      /ajouter
    defaults:  { _controller: SdzBlogBundle:Blog:ajouter }

sdzblog_modifier:
    path:      /modifier/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:modifier }
    requirements:
        id:  \d+

sdzblog_supprimer:
    path:      /supprimer/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:supprimer }
    requirements:
        id:  \d+

N'oubliez pas de bien ajouter le préfixe /blog lors de l'import de ce fichier, dans app/config/routing.yml :

1
2
3
4
5
# app/config/routing.yml

SdzBlogBundle:
    resource:  "@SdzBlogBundle/Resources/config/routing.yml"
    prefix:    /blog

Pour conclure

Ce chapitre est terminé, et vous savez maintenant tout ce qu'il faut savoir sur le routeur et les routes.

Retenez que ce système de routes vous permet premièrement d'avoir des belles URL, et deuxièmement de découpler le nom de vos URL du nom de vos contrôleurs. Ajoutez à cela la génération d'URL, et vous avez un système extrêmement flexible et maintenable.

Le tout sans trop d'efforts !

Pour plus d'informations sur le système de routes, n'hésitez pas à lire la documentation officielle.


En résumé

  • Une route est composée au minimum de deux éléments : l'URL à faire correspondre (son path), et le contrôleur à exécuter (attribut _controller).
  • Le routeur essaie de faire correspondre chaque route à l'URL appelée par l'internaute, et ce dans l'ordre d'apparition des routes : la première route qui correspond est sélectionnée.
  • Une route peut contenir des arguments, facultatifs ou non, représentés par les accolades {argument}, et dont la valeur peut être soumise à des contraintes via la section requirements.
  • Le routeur est également capable de générer des URL à partir du nom d'une route, et de ses paramètres éventuels.