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 :
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_home:
path: /platform
defaults: { _controller: OCPlatformBundle:Advert:index }
oc_platform_view:
path: /platform/advert/{id}
defaults: { _controller: OCPlatformBundle:Advert:view }
oc_platform_add:
path: /platform/add
defaults: { _controller: OCPlatformBundle:Advert:add }
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_home:
path: /platform
defaults: { _controller: OCPlatformBundle:Advert:index }
oc_platform_view:
path: /platform/advert/{id}
defaults: { _controller: OCPlatformBundle:Advert:view }
oc_platform_add:
path: /platform/add
defaults: { _controller: OCPlatformBundle:Advert:add }
Et voici en texte le fonctionnement, pas à pas :
- On appelle l'URL
/platform/advert/5
. - Le routeur essaie de faire correspondre cette URL avec le
path
de la première route. Ici,/platform/advert/5
ne correspond pas du tout à/platform
(lignepath
de la première route). - Le routeur passe donc à la route suivante. Il essaie de faire correspondre
/platform/advert/5
avec/platform/advert/{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 :/platform/advert
(URL) =/platform/advert
(route) ;5
(URL) ={id}
(route).
- Le routeur s'arrête donc, il a trouvé sa route.
- Il demande à la route : « Quels sont tes paramètres de sortie ? », la route répond : « Mes paramètres sont 1/ le contrôleur
OCPlatformBundle:Advert:view
, et 2/ la valeur$id = 5
. » - Le routeur renvoie donc ces informations au Kernel (le noyau de Symfony2).
- Le noyau va exécuter le bon contrôleur avec les bons paramètres !
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, «
soc_platform_home » si vous êtes sur la page
/platform
. 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.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 « OCPlatformBundle:Advert:view », vous avez trois
informations :
- « OCPlatformBundle » 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/OC/PlatformBundle
. - « Advert » est le nom du contrôleur à ouvrir. En terme de fichier, cela correspond à
Controller/AdvertController.php
dans le répertoire du bundle. Dans notre cas, nous avons comme chemin absolusrc/OC/PlatformBundle/Controller/AdvertController.php
. - « view » 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 :
public function viewAction()
.
Les routes de base
Étudions la première route plus en détail :
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_home:
path: /platform
defaults: { _controller: OCPlatformBundle:Advert:index }
oc_platform_home:
path: /platform
defaults: { _controller: OCPlatformBundle:Advert:index }
Ce bloc représente ce que l'on nomme une « route ». Elle est constituée au minimum de trois éléments :
oc_platform_home
est le nom de la route. Il n'a aucune importance dans le travail du routeur pour trouver le bon contrôleur étant donné une URL. 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 « oc_platform » pour l'unicité entre bundles (imaginez un autre bundle avec une route « home » !).path: /platform
est l'URL sur laquelle la route s'applique. Ici, « /platform » correspond à une URL absolue du typehttp://www.monsite.com/platform
.defaults: { _controller: OCPlatformBundle:Advert:index }
correspond aux paramètres de sortie de la route. Ici, seul le contrôleur à appeler est mentionné, mais ce tableaudefaults
peut contenir d'autres paramètres.
Créer une route avec des paramètres
Reprenons la deuxième route de notre exemple :# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_view:
path: /platform/advert/{id}
defaults: { _controller: OCPlatformBundle:Advert:view }
Je vous invite à créer la méthode correspondante dans le contrôleur :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class AdvertController extends Controller
{
// La route fait appel à OCPlatformBundle:Advert:view,
// on doit donc définir la méthode viewAction.
// On donne à cette méthode l'argument $id, pour
// correspondre au paramètre {id} de la route
public function viewAction($id)
{
// $id vaut 5 si l'on a appelé l'URL /platform/advert/5
// Ici, on récupèrera depuis la base de données
// l'annonce correspondant à l'id $id.
// Puis on passera l'annonce à la vue pour
// qu'elle puisse l'afficher
return new Response("Affichage de l'annonce d'id : ".$id);
}
// ... et la méthode indexAction que nous avons déjà créée
}
N'oubliez pas de tester votre code à l'adresse suivante : http://localhost/Symfony/web/app_dev.php/platform/advert/5, et amusez-vous à changer la valeur du paramètre dans l'URL.
Vous pouvez bien sûr multiplier les paramètres au sein d'une même route. Ajoutez cette route juste après la route oc_platform_view, pour l'exemple :
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_view_slug:
path: /platform/{year}/{slug}.{format}
defaults: { _controller: OCPlatformBundle:Advert:viewSlug }
Cette route permet d'intercepter les URL suivantes :
/platform/2011/webmaster-aguerri.html
ou /platform/2012/symfony.xml
, etc. Et voici la méthode correspondante qu'on aurait côté contrôleur :<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class AdvertController extends Controller
{
// On récupère tous les paramètres en arguments de la méthode
public function viewSlugAction($slug, $year, $format)
{
return new Response(
"On pourrait afficher l'annonce correspondant au
slug '".$slug."', créée en ".$year." et au format ".$format."."
);
}
}
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 /platform/2011/webmaster.aguerri.html
ne va pas correspondre à cette route, car :{annee}
= 2011 ;{slug}
= webmaster ;{format}
= aguerri ;- ? = html ;
Les routes avancées
Créer une route avec des paramètres et leurs contraintes
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_view_slug:
path: /platform/{year}/{slug}.{format}
defaults: { _controller: OCPlatformBundle:Advert:viewSlug }
requirements:
year: \d{4}
format: html|xml
oc_platform_view_slug:
path: /platform/{year}/{slug}.{format}
defaults: { _controller: OCPlatformBundle:Advert:viewSlug }
requirements:
year: \d{4}
format: html|xml
-
\d{4}
veut dire « quatre chiffres à la suite ».
html|xml
signifie « soit HTML, soit XML ». L'URL/platform/2011/webmaster.rss
ne sera donc pas interceptée.
# src/OC/PlatformBundle/Resources/config/routing.yml
oc_platform_view_slug:
path: /platform/{year}/{slug}.{format}
defaults: { _controller: OCPlatformBundle:Advert:viewSlug, format: html }
requirements:
year: \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 !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
Faites le test : modifiez le nom du paramètre de la route à {format}
, ajoutez juste un underscore), alors un header avec le Content-type
correspondant est ajouté à la réponse retournée. Exemple : vous appelez /platform/2014/webmaster.xml
et
le Kernel sait que la réponse retournée par le contrôleur est du XML,
grâce au paramètre "_format" contenu dans la route. Ainsi, avant
d'envoyer la réponse à notre navigateur, le header Content-type: application/xml
sera ajouté.{_format}
, n'oubliez pas de changer le nom de l'argument de la méthode viewSlugAction
à $_format
également, et essayez d'atteindre la page /platform/2014/webmaster.xml.
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.
Le paramètre
{_controller}
Eh oui, cette valeur que nous avons toujours mise dans le tableau
defaults
n'est rien d'autre qu'un paramètre de route ! Evidemment, c'est un paramètre que nous ne mettons jamais dans le path
de nos routes, mais je tenais à vous montrer qu'il n'est pas différent des autres. Le tableau defaults
correspond juste aux valeurs par défaut de nos paramètres, qu'ils soient ou non présent dans le path
de la route.Ajouter un préfixe lors de l'import de nos routes
Vous avez remarqué que nous avons mis
/platform
au début du path
de chacune de nos routes. En effet, on crée un site et on aimerait que tout ce qui touche à la plateforme ait ce préfixe /platform
.
Au lieu de le répéter dans chaque route, Symfony2 vous propose de
rajouter un préfixe lors de l'import du fichier de route de notre
bundle.
Modifiez donc le fichier
app/config/routing.yml
comme suit :
# app/config/routing.yml
oc_platform:
resource: "@OCPlatformBundle/Resources/config/routing.yml"
prefix: /platform
oc_platform:
resource: "@OCPlatformBundle/Resources/config/routing.yml"
prefix: /platform
Vous pouvez ainsi enlever la partie
Bonus : si un jour vous souhaitez changer /platform
de chacune de vos routes./platform
par /awesomePlatform
, vous n'aurez à modifier qu'une seule ligne.Générer des 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
$this->get('router')->generate()
qu'il faut appeler. Par exemple :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class AdvertController extends Controller
{
public function indexAction()
{
// On veut avoir l'URL de l'annonce d'id 5.
$url = $this->get('router')->generate(
'oc_platform_view', // 1er argument : le nom de la route
array('id' => 5) // 2e argument : les valeurs des paramètres
);
// $url vaut « /platform/advert/5 »
return new Response("L'URL de l'annonce d'id 5 est : ".$url);
}
}
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class AdvertController extends Controller
{
public function indexAction()
{
// On veut avoir l'URL de l'annonce d'id 5.
$url = $this->get('router')->generate(
'oc_platform_view', // 1er argument : le nom de la route
array('id' => 5) // 2e argument : les valeurs des paramètres
);
// $url vaut « /platform/advert/5 »
return new Response("L'URL de l'annonce d'id 5 est : ".$url);
}
}
Vous voyez qu'il est très facile de générer des URL. La méthode
generate
a besoin de 2 argument :- Le premier est tout simplement le nom de la route ;
- Le deuxième est un tableau contenant les valeurs des paramètres pour la génération. En effet, l'objectif du routeur n'est pas de générer
/platform/advert/{id}
qui n'aurait pas de sens, mais de générer une URL prête à être utilisée, dans notre cas de l'annonce d'id 5 :/platform/advert/5.
Ce 2e argument est bien sûr facultatif si votre route n'utilise pas de paramètre.
Pour générer une URL absolue, lorsque vous l'envoyez par e-mail par exemple, il faut mettre le troisième argument de la méthode
generate
à true
. Exemple :
<?php
$url = $this->get('router')->generate('oc_platform_home'), array(), true);
$url = $this->get('router')->generate('oc_platform_home'), array(), true);
Ainsi,
$url
vaut http://monsite.com/platform
et pas uniquement /platform
.
Car notre contrôleur hérite du contrôleur de base de Symfony, nous avons
également accès à une méthode raccourcie pour générer des routes. Voici
deux méthodes strictement équivalentes :
<?php
// Depuis un contrôleur
// Méthode longue
$url = $this->get('router')->generate('oc_platform_home');
// Méthode courte
$url = $this->generateUrl('oc_platform_home');
// Depuis un contrôleur
// Méthode longue
$url = $this->get('router')->generate('oc_platform_home');
// Méthode courte
$url = $this->generateUrl('oc_platform_home');
2. Depuis une vue Twig (notre moteur de template)
Vous aurez bien plus l'occasion de devoir générer une URL depuis les vues. C'est la fonction
path
qu'il faut utiliser depuis un template Twig :
{# Dans une vue Twig, en considérant bien sûr
que la variable advert_id est disponible #}
<a href="{{ path('oc_platform_view', { 'id': advert_id }) }}">
Lien vers l'annonce d'id {{ advert_id }}
</a>
que la variable advert_id est disponible #}
<a href="{{ path('oc_platform_view', { 'id': advert_id }) }}">
Lien vers l'annonce d'id {{ advert_id }}
</a>
Et pour générer une URL absolue depuis Twig, pas de troisième argument, mais on utilise la fonction
Voilà : vous savez générer des URL, ce n'était vraiment pas compliqué. Pensez bien à utiliser la fonction url()
au lieu de path()
.
Elle s'utilise exactement de la même manière, seul le nom change. Pas
de panique par rapport à la syntaxe de Twig, nous l'étudions en détails
dans un prochain chapitre.{{ path }}
pour tous vos liens depuis vos templatesPour 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 (paramètre_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 paramètres, facultatifs ou non, représentés par les accolades {paramètre}, 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.
Commentaires
Enregistrer un commentaire