Gérer les routes du module vers un contrôleur d'un module Drupal

Drupal 8

Gérer les routes du module vers un contrôleur d'un module Drupal

Soumis par Antoine le mar 17/03/2020 - 16:22

Le but d’une route est d’aiguiller l’utilisateur vers un contrôleur, en fonction de l’URL qu’il a saisi. Le contrôleur pourra alors effectuer des traitements et afficher du contenu.

Créer un contrôleur

Une route pointe vers un contrôleur. Nous allons commencer par en créer un basique. Dans le répertoire de votre module :

  1. créer un répertoire « src/controller »
  2. créer un fichier NomDuControlleurController.php Le nom du contrôleur peut comporter plusieurs mots mais chaque mot commence par une majuscule (même le premier) et doit finir par Controller.php
  3. Dans ce fichier, il faut copier le code suivant :
<?php

namespace Drupal\premiermo\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Returns responses for premiermo routes.
 */
class PremiermoController extends ControllerBase {
   Public function premierefonction() {
      $toto['content'] = [
        '#type' => 'item',
        '#markup' => $this->t("Hello !"),
      ];
      return $toto;
    }
}

Explication du code

namespace Drupal\premiermo\Controller; Le namespace permet de rendre nos fonctions, constantes et variables spécifiques au controller de notre module.

use Drupal\Core\Controller\ControllerBase; On importe la classe ControllerBase du namespace « Drupal\Core\ControllerBase dans notre namespace.

class PremiermoController extends ControllerBase {Permet d’étendre la classe ControllerBase avec la classe « PremiermoController ». De cette façon on peut utiliser les méthodes de la classe ControllerBase. Attention Drupal utilise la norme PSR-4 pour gérer les namespace. Cette norme indique qu’un fichier doit contenir une seule classe et que le nom du fichier doit correspondre au nom de cette classe.

Comme il s’agit d’un contrôleur, on a étendu la classe ControllerBase qui fournit des méthodes de base d’un contrôleur :

  • I() pour créer des liens,
  • t() pour traduire des chaines dans la langue de l’utilisateur,
  • currentUser() pour obtenir des informations sur l’utilisateur

Nous verrons par la suite qu’il existe d’autres classes plus utiles.

Enfin, on écrit une fonction publique qui va générer du contenu lorsqu’elle sera appelée par une route. Dans cet exemple, nous utilisons un render array. Nous verrons par la suite comment utiliser les render array pour générer du contenu.

Maintenant que nous avons un contrôleur qui génère du contenu, nous allons l’appeler avec une route.

Créer une route simple

Les routes sont définies dans un fichier nommodule.routing.yml situé à la racine du dossier du module. Chaque route aura un nom système puis un ensemble de clé : valeur qui permet de la décrire. Vous trouverez à cette adresse la documentation sur les routes : https://www.drupal.org/docs/8/api/routing-system/structure-of-routes

  1. Créer un fichier premiermo.routing.yml et y ajouter le code suivant :
premiermo.premiereroute:
  path: '/premiereroute'
  defaults:
    _title: 'This is my first route'
    _controller: '\Drupal\premiermo\Controller\PremiermoController::premierefonction'
  requirements:
    _permission: 'access content'

Rappel : Après chaque modification d’un fichier yml, il faut vider le cache.

Rendez vous à l’adresse monsite/premiereroute. Il devrait être écrit « Hello ! »

Explication du code

premiermo.premiereroute: correspond au nom système de la route. A l’aide de ce nom, il sera possible d’appeler et modifier cette route avec du code. Ce nom doit être unique, C’est pourquoi, généralement on définit la clé sous la forme nom_module.nom_page avec un nom page qui correspond à ce que la page va faire

  path: '/premiereroute' indique l’URL de la route. Elle doit commencer par un /

  defaults:
    _title:
'>This is my first route' indique le titre de la page chargée
   
_controller: '\Drupal\premiermo\Controller\PremiermoController::premierefonction' donne le chemin d’accès du contrôleur ainsi que le nom de la fonction à utiliser. Ce chemin d’accès aura la forme « \Drupal\nom_module\Controller\nom_contrôleur ::nom_de_la_fonction

  requirements:
    _permission:
'access content' permet de définir les droits nécessaire pour accéder à la route. Ici, il faut avoir le droit « Voir le contenu publié » qui est accordé par défaut aux utilisateurs anonymes et ceux authentifiés. Nous verrons par la suite comment gérer des droits supplémentaires.

Passer des paramètres dans la route

Il est possible de passer des paramètres dans la route. Pour cela, il faut :

  1. Modifier la valeur de la clé « path » dans la route en ajoutant des paramètres entre accolades et séparés par des /. Attention votre route peut avoir au maximum 9 niveaux.
  2. Ajouter les paramètres dans la fonction du contrôleur appelée par la route

  path: '/premiereroute/{premier_param}/{second_param}'
Dans l’exemple ci-dessous nous allons ajouter deux paramètres dans la route « premiermo.premiereroute »

//Fichier premiermo.routing.yml
premiermo.premiereroute:
  path: '/premiereroute/{premier_p}/{second_p}'
  defaults:
    _title: 'This is my first route'
    _controller: '\Drupal\premiermo\Controller\PremiermoController::premierefonction'
  requirements:
    _permission: 'access content'

 Puis nous modifions le contrôleur pour afficher ces paramètres :

//Fichier PremiermoController.php
public function premierefonction($premier_p, $second_p) {
  $toto['content'] = [
    '#type' => 'item',
    '#markup' => $this->t("Great ! Parameters are $premier_p and $second_p"),
  ];
  return $toto;
}

Rendez vous à l’adresse « monsitesite/premiereroute/coucou/toto ». Il devrait être affiché : « Ca marche ! les paramètres sont coucouc et toto »

Gérer les accès de la route avec la clé "requirements"

La clé requirement est obligatoire. Si aucune valeur ne lui est associé, la route renverra une erreur 403 acces denied.

Valider les paramètres avec une expression régulière

Il est possible de vérifier à l’aide d’expressions régulières si les valeurs des paramètres indiquées dans l’URL correspondent à des critères. Pour cela, il faut rajouter dans la partie requirements nomduparametre : 'expression_reguliere'. Si les critères ne sont pas respectés, la route renvoie une erreur 404

Exemple :

premiermo.premiereroute:
  path: '/premiereroute/{premier_p}/{second_p}'
  defaults:
    _title: 'Ceci est ma première route'
    _controller: 
'\Drupal\premiermo\Controller\PremiermoController::premierefonction'
  requirements:
    _permission: 'access content'
    premier_p: '[a-zA-Z]+'
    second_p: '[0-9]{1}'

Dans cette exemple, le premier paramètre doit être une chaîne de caractères en minuscule ou majuscule qui comprend au minimum 1 caractère (à cause du +). Le second paramètre doit être un seul nombre entier (à cause du {1}). 

Le site https://regexr.com/ permet de tester et d’expliquer les expressions régulières PRCE.

Gérer des accès à travers les droits des utilisateurs avec la sous clé _permission

Il est possible de déterminer les droits nécessaires pour accéder à une page à travers la sous clé _permission de la clé requirements d’une route. Si l’utilisateur n’a pas les droits, la route renvoie une erreur 403 access denied.

Attention : quand vous tester les autorisations, si vous êtes connecté en tant qu’admin, vous avec automatiquement tous les droits !

Définir le droit

Dans le fichier nomdumodule.routing.yml, ajouter la clé requirements et la sous clé _permission : 'Le nom du droit'.

premiermo.premiereroute:
  path: '/premiereroute/{premier_p}/{second_p}'
  defaults:
    _title: 'Ceci est ma première route'
    _controller: '\Drupal\premiermo\Controller\PremiermoController::premierefonction'
  requirements:
    _permission: 'access content'

Dans cette exemple, le droit access content correspond à « Voir le contenu publié ».

Il est possible de demander plusieurs droit en les séparant par une « , » pour signifier « AND » et un « + » pour signifier « OR ».

Ajouter un droit dans l'interface admin

Si vous voulez définir un nouveau droit vous devez le créer dans le fichier nomdumodule.permissions.yml situé à la racine de votre module puis l’utiliser dans le fichier nomdumodule.routing.yml.

Exemple de fichier premiermo.permissions.yml

mon droit a moi:
  title: 'Mon droit que je suis le seul à avoir'
  description: "On peut écrire ce qu'on veut."
  restrict access: false

Le résultat dans la partie « droits » de la zone « admin »

Si le droit n’apparait pas, faites un drush cr, et vérifier la syntaxe du fichier yml

Fichier premiermo.routing.yml

premiermo.premiereroute:
  path: '/premiereroute/{premier_p}/{second_p}'
  defaults:
    _title: 'Ceci est ma première route'
    _controller: '\Drupal\premiermo\Controller\PremiermoController::premierefonction'
  requirements:
    _permission: 'mon droit a moi'

Accorder les droits à des utilisateurs lors de l’installation du module

Si par défaut vous souhaitez accorder certains droits lors de l’installation du module, vous devez :

Créer le fichier premiermo.install à la racine de votre module

Saisir le code suivant :

<?php

/**
 * @file
 * Install, update and uninstall functions for the premiermo module.
 */

 use Drupal\user\RoleInterface;

/**
 * Implements hook_install().
 */
function premiermo_install() {
  \Drupal::messenger()->addStatus(__FUNCTION__);
  user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
         'le nom du droit' => TRUE,
       ));

}

On commence par charger l’interface RoleInterface avec « use Drupal\user\RoleInterface; » qui se trouve à cette adresse : monsite\core\modules\user\src\RoleInterface.php

Ensuite on crée la fonction qui est lancée lors de l’installation du module « function premiermo_install() { »

Enfin on rajoute le code qui permet d’ajouter une permission aux utilisateurs non identifiés :

user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
         'le nom du droit' => TRUE,
       ));

L’interface RoleInterface fourni deux constantes : « ANONYMOUS_ID » et « AUTHENTICATED_ID ». Ici le droit est défini pour ANONYMOUS_ID

La fonction user_role_change_permissions est fournie par le module user du core.

Gérer les droits d'accès à partir des rôles avec la sous clé _role

Comme vous l'avez vu dans le premier tuto, il est possible de définir des rôles qui disposent d'un ensemble de droits. Il est possible d’autoriser l’accès à une route avec la sous clé _role. Dans l’exemple ci-dessous, seul les administrateurs peuvent accéder à la route :

premiermo.example:
  path: '/premiermo/example'
  defaults:
    _title: 'Example'
    _controller: '\Drupal\premiermo\Controller\PremiermoController::build'
  requirements:
    _role: 'administrator'

Il est possible de mettre plusieurs rôles en les séparant avec des « , » pour signifier « AND » et des « + » pour signifier « OR ». _role: organizer,participant,controller signifie qu’il faut avoir les 3 rôles pour accéder à la page.

Pour trouver le nom système d’un rôle, il faut le modifier : admin à personnes à onglet rôles à bouton modifier.

Les autres clés

Il existe d’autres sous clés qui permettent de gérer l’accès en fonction

  • Du format de la requête
  • Du droit d’accès à un type d’entité

La documention de drupal sur les routes

Version