Overblog
Editer l'article Suivre ce blog Administration + Créer mon blog

Le routage

Publié le par Penda Jose

URLs

Si vous cliquez sur une offre sur la page d'accueil Jobeet, l'URL ressemble à ceci: /job/1/show. Si vous avez déjà développé des sites web PHP, vous êtes probablement plus habitués à des URL comme /job.php?id=1. Comment Symfony les fait fonctionner? Comment Symfony détermine l'action à appeler à partir de cette URL? Pourquoi l'id de l'offre est-il récupéré avec le paramètre $id dans l'action? Ici, nous allons répondre à toutes ces questions.

Vous avez déjà vu le code suivant dans le template src/Ens/JobeetBundle/Resources/views/job/index.html.twig:

{{ path('ens_job_show', { 'id': entity.id }) }}

Celui-ci utilise la fonction de l'helper template path pour générer l'url pour l'offre qui a l'id 1. ens_job_show est le nom de la route utilisée, définie dans la configuration comme vous le verrez ci-dessous.

Configuration du routage

Dans Symfony2, la configuration du routage se fait habituellement dans le fichier app/config/routing.yml. Ceci importe la configuration du routage d'un paquet spécifique. Dans notre cas, le fichier src/Ens/JobeetBundle/Resources/config/routing.yml est importé:

 
  1. # app/config/routing.yml
  2. EnsJobeetBundle:
  3. resource: "@EnsJobeetBundle/Resources/config/routing.yml"
  4. prefix: /

Maintenant, si vous regardez dans le fichier routing.yml de JobeetBundle vous verrez qu'il importe un autre fichier de routage, celui pour le contrôleur Job et définit une route appelée EnsJobeetBundle_homepage pour le modèle d'URL /hello/{name}:

 
  1. # src/Ens/JobeetBundle/Resources/config/routing.yml
  2. EnsJobeetBundle_job:
  3. resource: "@EnsJobeetBundle/Resources/config/routing/job.yml"
  4. prefix: /job
  5. EnsJobeetBundle_homepage:
  6. pattern: /hello/{name}
  7. defaults: { _controller: EnsJobeetBundle:Default:index }
 
  1. # src/Ens/JobeetBundle/Resources/config/routing/job.yml
  2. ens_job:
  3. pattern: /
  4. defaults: { _controller: "EnsJobeetBundle:Job:index" }
  5. ens_job_show:
  6. pattern: /{id}/show
  7. defaults: { _controller: "EnsJobeetBundle:Job:show" }
  8. ens_job_new:
  9. pattern: /new
  10. defaults: { _controller: "EnsJobeetBundle:Job:new" }
  11. ens_job_create:
  12. pattern: /create
  13. defaults: { _controller: "EnsJobeetBundle:Job:create" }
  14. requirements: { _method: post }
  15. ens_job_edit:
  16. pattern: /{id}/edit
  17. defaults: { _controller: "EnsJobeetBundle:Job:edit" }
  18. ens_job_update:
  19. pattern: /{id}/update
  20. defaults: { _controller: "EnsJobeetBundle:Job:update" }
  21. requirements: { _method: post }
  22. ens_job_delete:
  23. pattern: /{id}/delete
  24. defaults: { _controller: "EnsJobeetBundle:Job:delete" }
  25. requirements: { _method: post }

Voyons de plus près la route ens_job_show. Le modèle défini par ens_job_show agit comme /*/show où le joker est l'id. Pour l'URL /1/show, la variable id obtient une valeur de 1, qui est disponible pour vous permettre de l'utiliser dans votre contrôleur. Le paramètre _controller est une entrée spéciale qui dit à Symfony quel contrôleur/action doit être exécuté quand une URL correspond à cette route. Dans notre cas, il doit exécuter showAction de JobController dans EnsJobeetBundle.

Les paramètres de route (par exemple, {id}) sont particulièrement importants parce que chacun est mis à disposition en tant qu'argument à la méthode du contrôleur:

 
  1. public function showAction($id)
  2. {
  3. // ...
  4. }

Configuration du routage en environnement dev

L'environnement de dev charge le fichier app/config/routing_dev.yml qui contient les routes utilisées par la Web Debug Toolbar, entre autres. Ce fichier charge, à la fin, le fichier de configuration principal routing.yml.

Si vous allez à http://jobeet.local/app_dev.php, vous verrez la page par défaut de Symfony. Nous allons changer cela pour qu'à l'avenir l'environnement de dev affiche les mêmes pages que celui de production. Ouvrez votre app/config/routing_dev.yml et enlevez les 3 premières routes qui sont relatives au paquet de démonstration de Symfony. Maintenant, le fichier routing_dev.yml devrait ressembler à ceci:

 
  1. # app/config/routing_dev.yml
  2. _assetic:
  3. resource: .
  4. type: assetic
  5. _wdt:
  6. resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
  7. prefix: /_wdt
  8. _profiler:
  9. resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
  10. prefix: /_profiler
  11. _configurator:
  12. resource: "@SensioDistributionBundle/Resources/config/routing/webconfigurator.xml"
  13. prefix: /_configurator
  14. _main:
  15. resource: routing.yml

N'oubliez pas de vider le cache après cette modification.

php app/console cache:clear --env=prod
php app/console cache:clear --env=dev

 

Personnalisation des routes

Pour l'instant, lorsque vous demandez l'URL / dans un navigateur, vous obtenez une erreur 404. C'est parce que cette URL ne correspond à aucune des routes définies. Nous avons une route EnsJobeetBundle_homepage qui correspond à l'URL /hello/jobeet et nous envoie à l'action index de DefaultController. Nous allons la changer pour correspondre à l'URL / et appeler l'action index de JobController. Pour faire le changement, modifiez comme ci-dessous:

 


	# src/Ens/JobeetBundle/Resources/config/routing.yml
	# ...
	 
	EnsJobeetBundle_homepage:
	pattern:  /
	defaults: { _controller: EnsJobeetBundle:Job:index }


Maintenant, si vous effacez le cache et allez à http://jobeet.local, vous verrez la page d'accueil Job. Nous pouvons maintenant modifier le lien du logo Jobeet dans le layout pour utiliser la route EnsJobeetBundle_homepage:

 


	<!-- src/Ens/JobeetBundle/Resources/views/layout.html.twig -->
	<!-- ... -->
	<h1><a href="{{ path('EnsJobeetBundle_homepage') }}">
	<img src="{{ asset('bundles/ensjobeet/images/logo.jpg') }}" alt="Jobeet Job Board" />
	</a></h1>
	<!-- ... -->


Pour quelque chose d'un peu plus compliqué, nous allons changer l'URL d'une offre avec quelque chose de plus significatif:

/job/sensio-labs/paris-france/1/web-developer

Sans rien savoir de Jobeet, et sans regarder la page, vous pouvez comprendre à partir de l'URL que Sensio Labs est à la recherche d'un Développeur Web pour travailler à Paris, France.

Le schéma ci-dessous correspond à une telle URL:

/job/{company}/{location}/{id}/{position}

Modifiez la route ens_job_show à partir du fichier job.yml:

 


	# src/Ens/JobeetBundle/Resources/config/routing/job.yml
	# ...
	 
	ens_job_show:
	pattern:  /{company}/{location}/{id}/{position}
	defaults: { _controller: "EnsJobeetBundle:Job:show" }


Maintenant, nous avons besoin de passer tous les paramètres de la route modifiée pour que cela fonctionne:

 


	<!-- src/Ens/JobeetBundle/Resources/views/Job/index.html.twig -->
	<!-- ... -->
	<a href="{{ path('ens_job_show', { 'id': entity.id, 'company': entity.company, 'location': entity.location, 'position': entity.position }) }}">
	{{ entity.position }}
	</a>
	<!-- ... -->


Si vous regardez les URLs générées, elles ne sont pas encore tout à fait comme nous voulons qu'elles soient:

http://jobeet.local/job/Sensio Labs/Paris, France/1/Web Developer

Nous avons besoin de "remodeler" les valeurs de chaque colonne en remplaçant tous les caractères non ASCII par un tiret (-). Ouvrez le fichier Job.php et ajoutez les méthodes suivantes à la classe:

 


	// src/Ens/JobeetBundle/Entity/Job.php
	// ...
	 
	use Ens\JobeetBundle\Utils\Jobeet as Jobeet;
	class Job
	{
	// ...
	public function getCompanySlug()
	{
	return Jobeet::slugify($this->getCompany());
	}
	 
	public function getPositionSlug()
	{
	return Jobeet::slugify($this->getPosition());
	}
	 
	public function getLocationSlug()
	{
	return Jobeet::slugify($this->getLocation());
	}
	}


Ensuite, créez le fichier src/Ens/JobeetBundle/Utils/Jobeet.php et ajoutez la méthode slugify():

 


	// src/Ens/JobeetBundle/Utils/Jobeet.php
	 
	namespace Ens\JobeetBundle\Utils;
	class Jobeet
	{
	static public function slugify($text)
	{
	// replace all non letters or digits by -
	$text = preg_replace('/\W+/', '-', $text);
	 
	// trim and lowercase
	$text = strtolower(trim($text, '-'));
	 
	return $text;
	}
	}


Nous avons défini trois nouveaux accesseurs "virtuels": getCompanySlug(), getPositionSlug(), et getLocationSlug(). Ils retournent la valeur correspondant à leur colonne après avoir appliqué la méthode slugify(). Maintenant, vous pouvez remplacer les noms réels des colonnes par les virtuels dans le modèle:

 


	<!-- src/Ens/JobeetBundle/Resources/views/Job/index.html.twig -->
	<!-- ... -->
	<a href="{{ path('ens_job_show', { 'id': entity.id, 'company': entity.companySlug, 'location': entity.locationSlug, 'position': entity.positionSlug}) }}">
	{{ entity.position }}
	</a>
	<!-- ... -->


Vous aurez maintenant l'URL attendue:

http://jobeet.local/app_dev.php/job/sensio-labs/paris-france/1/web-developer

 

Les conditions dans les routes

Le système de routage a une fonction de validation intégrée. Chaque modèle de variable peut être validé par une expression régulière définie en utilisant l'entrée requirements d'une définition de route:

 


	# src/Ens/JobeetBundle/Resources/config/routing/job.yml
	# ...
	 
	ens_job_show:
	pattern: /{company}/{location}/{id}/{position}
	defaults: { _controller: "EnsJobeetBundle:Job:show" }
	requirements:
	id: \d+


L'entrée requirements ci-dessus oblige l'id à être une valeur numérique. Sinon, la route ne fonctionne pas.

 

Débugage des routes

Bien que l'ajout et la personnalisation de routes soit parlant, il est utile de pouvoir visualiser et obtenir des informations détaillées sur vos routes. Un excellent moyen de voir toutes les routes dans votre application se fait via la commande router:debug. Exécutez la commande en la lançant à partir de la racine de votre projet:

php app/console router:debug

La commande permet d'afficher une liste utile de toutes les routes configurées dans votre application. Vous pouvez également obtenir des renseignements très précis sur une seul route en incluant le nom de la route après la commande:

php app/console router:debug ens_job_show

 

Réflexions finales

Pour en savoir plus sur le système de routage Symfony2, lisez le chapitre Routing de la documentation officielle.
Commenter cet article