Symfony2 - Jobeet - Jour 05 - Le Routage

1 1 1 1 1 1 1 1 1 1 Rating 0.00 (0 Votes)
Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn

URL

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/Erlem/JobeetBundle/Resources/views/job/index.html.twig :

{{ path('erlem_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. erlem_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/Erlem/JobeetBundle/Resources/config/routing.yml est importé :

  •  app/config/routing.yml
erlem_jobeet:
    resource: "@ErlemJobeetBundle/Resources/config/routing.yml"
    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 ErlemJobeetBundle_homepage pour le modèle d'URL /hello/{name} :

  • src/Erlem/JobeetBundle/Resources/config/routing.yml
erlem_jobeet_homepage:
    path:     /hello/{name}
    defaults: { _controller: ErlemJobeetBundle:Default:index }

ErlemJobeetBundle_job:
    resource: "@ErlemJobeetBundle/Resources/config/routing/job.yml"
    prefix:   /job
  •  src/Erlem/JobeetBundle/Resources/config/routing/job.yml
erlem_job:
    pattern:  /
    defaults: { _controller: "ErlemJobeetBundle:Job:index" }

erlem_job_show:
    pattern:  /{id}/show
    defaults: { _controller: "ErlemJobeetBundle:Job:show" }

erlem_job_new:
    pattern:  /new
    defaults: { _controller: "ErlemJobeetBundle:Job:new" }

erlem_job_create:
    pattern:  /create
    defaults: { _controller: "ErlemJobeetBundle:Job:create" }
    requirements: { _method: post }

erlem_job_edit:
    pattern:  /{id}/edit
    defaults: { _controller: "ErlemJobeetBundle:Job:edit" }

erlem_job_update:
    pattern:  /{id}/update
    defaults: { _controller: "ErlemJobeetBundle:Job:update" }
    requirements: { _method: post|put }

erlem_job_delete:
    pattern:  /{id}/delete
    defaults: { _controller: "ErlemJobeetBundle:Job:delete" }
    requirements: { _method: post|delete }

Voyons de plus près la route erlem_job_show. Le modèle défini par erlem_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 ErlemJobeetBundle.

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.

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.

Personnalisation des Routes

Pour l'instant, lorsque vous demandez l'URL / dans un navigateur, vous obtiendrez une erreur 404 Not Found. C'est parce que cette URL ne correspond à aucun des itinéraires définis. Nous avons une route erlem_jobeet_homepage qui correspond à l'URL /hello/jobeet et nous envoie à l'action DefaultController. Nous allons le changer pour qu'il corresponde à l'URL / et d'appeler l'action index de JobController.

  • src/Erlem/JobeetBundle/Resources/config/routing.yml
erlem_jobeet_homepage:
    pattern:  /
    defaults: { _controller: ErlemJobeetBundle:Job:index }

ErlemJobeetBundle_job:
    resource: "@ErlemJobeetBundle/Resources/config/routing/job.yml"
    prefix:   /job

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 ErlemJobeetBundle_homepage :

  •  src/Erlem/JobeetBundle/Resources/views/layout.html.twig
<!-- ... -->    
    <h1><a href="/{{ path('erlem_jobeet_homepage') }}">
        <img alt="Jobeet Job Board" src="/{{ asset('bundles/erlemjobeet/images/logo.jpg') }}" />
    </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 erlem_job_show à partir du fichier job.yml :

  • src/Erlem/JobeetBundle/Resources/config/routing/job.yml
erlem_job_show:
    path:     /{company}/{location}/{id}/{position}
    defaults: { _controller: "ErlemJobeetBundle:Job:show" }

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

  • src/Erlem/JobeetBundle/Resources/views/Job/index.html.twig
<!-- ... -->
<a href={{ path('erlem_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/Erlem/JobeetBundle/Entity/Job.php
<?php

namespace Erlem\JobeetBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Erlem\JobeetBundle\Utils\Jobeet;

/**
 * Job
 */
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/Erlem/JobeetBundle/Utils/Jobeet.php et ajoutez la méthode slugify() :

  • src/Erlem/JobeetBundle/Utils/Jobeet.php
<?php

namespace Erlem\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/Erlem/JobeetBundle/Resources/views/Job/index.html.twig
<!-- ... -->
<a href={{ path('erlem_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/Erlem/JobeetBundle/Resources/config/routing/job.yml
erlem_job_show:
    pattern:  /{company}/{location}/{id}/{position}
    defaults: { _controller: "ErlemJobeetBundle: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 soient 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 seule route en incluant le nom de la route après la commande:

php app/console router:debug erlem_job_show

Réflexions finales

C'est tout pour aujourd'hui! Pour en savoir plus sur le système de routage Symfony2, lisez le chapitre Routing de la documentation officielle.

Code source

Le code source est sur GitHub. Vous pouvez le télécharger en exécutant les commandes ci-dessous (prérequis Symfony2 - Jobeet - Jour 01 - Démarrage du projet) :

su
cd /var/www/
git clone https://github.com/erlem/jobeet.git
cd jobeet/
git checkout tags/v0.5.0
 
composer update
 
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load
 
php app/console assets:install web

chmod 777 -R app/cache/
chmod 777 -R app/logs/

Vous pouvez maintenant tester l'application dans un navigateur: http://jobeet.local/ ou dans l'environnement de développement, http://jobeet.local/app_dev.php.


Symfony2 - Jour 04 - Le Contrôleur et la Vue
[Sommaire] Symfony2 - Jour 06 - Aller plus loin avec le Modèle >


Pour ce tutoriel, je me suis inspiré du tutoriel Symfony2 Jobeet du site IntelligentBee

Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn