Accéder au contenu principal

Le routeur de Symfony2

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 }

Et voici en texte le fonctionnement, pas à pas :
  1. On appelle l'URL /platform/advert/5.
  2. 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 (ligne path de la première route).
  3. 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).
  4. Le routeur s'arrête donc, il a trouvé sa route.
  5. 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. »
  6. Le routeur renvoie donc ces informations au Kernel (le noyau de Symfony2).
  7. 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 absolu src/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 }

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 type http://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 tableau defaults 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
  •  \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.

Utiliser des paramètres facultatifs Reprenons notre route et ajoutons-y la possibilité pour {format} de ne pas être renseigné :

# 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 {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é.
Faites le test : modifiez le nom du paramètre de la route à {_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

Vous pouvez ainsi enlever la partie /platform de chacune de vos routes.
Bonus : si un jour vous souhaitez changer /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);
    }
}

 

Vous voyez qu'il est très facile de générer des URL. La méthode generate a besoin de 2 argument :
  1. Le premier est tout simplement le nom de la route ;
  2. 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);

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');



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>

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. Pas de panique par rapport à la syntaxe de Twig, nous l'étudions en détails dans un prochain chapitre.
Voilà : vous savez générer des URL, ce n'était vraiment pas compliqué. Pensez bien à utiliser la fonction {{ path }} pour tous vos liens depuis vos templates


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 (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

Posts les plus consultés de ce blog

Zimbra install let's encrypt

 https://inguide.in/how-to-install-free-ssl-certificate-on-zimbra-mail-server/ Je change le domaine  ingu.pw In the article  Install Zimbra Mail Server o n CentOS 8, we learned to install Zimbra on CentOS. This article discusses the steps required to install the Let’s Encrypt free SSL certificate in Zimbra. Installing Free SSL Certificate on Zimbra: Method 1 This method is a proven one though you have to manually do all the steps. Another method discussed below is partially automatic, which might come in handy if you didn’t encounter any error during installation (working at the time of writing this article). So, let’s begin with method 1. First of all, add  epel repository  to the server 1 [root@mail ~]# yum -y install epel-release Install snapd Now, install  snapd  package with the following command 1 [root@mail ~]# sudo yum install snapd After the above step, you need to enable snapd. 1 [root@mail ~]# sudo systemctl enable --now snapd.socket Sometim...

Open Media Vault NAS change password

Known Root Password Login to the OMV using the root user and the current password via SSH or Console enter the following command passwd root The new password is now active. Unknown Root Password, but Admin Access to OMV GUI is Available In this scenario we still can help ourselves with the GUI. The method we use is, that we create a cron job for the root user which then resets the password. Navigate to System -> Cron Jobs Press the +Add button UN-tick the enabled box, so that the cronjob does not run automatically. put into the command field the following line, replace newpasswd with your password: echo "root:newpasswd" | chpasswd press okay select the newly created cron job Click the run button. in the opening window click the start button. It will shortly deactivate and activate again. open ssh or console and login as root with your new password. Root and Admin Password Unknown If you do not know the root password, you need to boot with a Li...

cPanel DDOS attack - Mitigate Slowloris Attacks - mod_qos

Apache mod_evasive Mod_evasive is a module available for the Apache HTTP server that can automatically block attacks by rate-limiting any IP that sends too many requests in a short time. Start by installing the module from WHM’s  EasyApache 4  interface. Select the  Currently Installed Packages  profile, search for  mod_evasive  in the  Apache Modules  section, and then install it. The default settings are good for most servers, but you can tweak them further by editing the configuration file  /etc/apache2/conf.d/300-mod_evasive.conf . You can also whitelist specific IP addresses or classes, so legitimate requests are not blocked. Configure CSF to block attacks While  mod_evasive  works very well, it only protects the Apache webserver. In order to harden other services as well, you can install the free  ConfigServer Security & Firewall  (CSF), which also includes a WHM plugin. As the  root  user, install CSF ...