Drupal 8 – partie 3 : création d’un module personnalisé

drupal8_logo

Dans un précédent article, nous avons pu constater que le CMF Drupal a bénéficié d’une réarchitecture complète dans sa version 8. Voyons à présent comment cette refonte du code PHP se traduit concrètement lors du développement d’un module custom sous Drupal 8.

Qu'allons-nous réaliser ?

Pour notre premier module développé pour Drupal 8, nous allons prendre un exemple simple : nous voulons créer une page personnalisée via un code correctement organisé, c'est-à-dire en utilisant le modèle MVC et ce qui va avec (un contrôleur, une vue, une route).

Comment procéder ?

Mise en place de la structure minimaliste d'un module

Pour commencer, créons dans le dossier /modules/custom un répertoire dont le nom sera le nom « machine » du module, par exemple hello_world. Vous pouvez vérifier la disponibilité de ce nom en allant sur https://www.drupal.org/project/hello_world (dans l’éventualité d’un partage avec la communauté Drupal).

Il faut ensuite créer le fichier contenant les informations générales du module, qui aurait été nommé en Drupal 7 hello_world.info mais qui devient en Drupal 8 hello_world.info.yml. En effet, les fichiers de configuration de Drupal 8 sont tous en YAML, un format permettant de décrire des données de manière concise.

Voici un exemple relativement complet de ce fichier .info.yml :

name: My first module (Hello World)
description: Un module de démontration sur D8
type: module
core: 8.x
version: 8.x-1.x-dev
package: Netapsys

Les propriétés ci-dessus et leurs valeurs parlent d’elles-mêmes. Notons que comme en Drupal 7, on peut utiliser la propriété package pour regrouper les modules dans le backoffice.

Ces quelques lignes suffisent à créer un module sans fonctionnalités :

mod_drupal1

 

Création d'une nouvelle route

La création d’une nouvelle page dans Drupal 8 est semblable à la méthode utilisée par Symfony 2 : il faut définir une route (une URL reliée à un contrôleur) et créer ledit contrôleur. Drupal 8 utilise en effet l'architecture MVC (Modèle Vue Contrôleur).

Ici le chemin de la page créé par notre module sera /hello et elle appellera le contrôleur HelloController.

Nous allons définir la route dans le fichier hello_world.routing.yml :

hello_world.hello:
  path: '/hello'
  defaults:
    _controller: '\Drupal\hello_world\Controller\HelloController::world'
    _title: 'Mon premier module'
  requirements:
    _permission: 'access content' 

Détaillons pas à pas la syntaxe du routing :

  • L1 : on donne un identifiant unique à la route : ici on la nomme hello, et préfixée du nom du module cela donne hello_world.hello.
  • L2 : la propriété path permet de définir le chemin de la page que nous allons créer. Ici l’url sera du type <racine>/hello où <racine> est l’url racine du site.
  • L4 : on indique le contrôleur correspondant à la route et la méthode à appeler (ici le contrôleur s’appelle HelloController -ce sera nom de sa classe- et la méthode de contrôleur utilisée est world)
  • L5 : on donne un titre à la page (il apparaîtra dans la balise title et en h1 par défaut)
  • L7 : tous les utilisateurs ayant le droit d’accès au contenu du site pourront voir la page

 

Création du contrôleur

Il nous faut ensuite définir le contrôleur correspondant à la route ci-dessus, ainsi que la méthode appelée.

Pour ce faire, créez le dossier src/Controller à l’intérieur du dossier du module. Puis créez le fichier HelloController.php qui va contenir la classe Hello dotée de la méthode world.

namespace Drupal\hello_world\Controller;
use Drupal\Core\Controller\ControllerBase;

class HelloController extends ControllerBase {

    /**
     * Méthode appelée dans le routing via l'instruction :
     * _controller: '\Drupal\hello_world\Controller\HelloController::world' \Drupal\hello_world\Controller\HelloController::world
     * @return  array  tableau de rendu spécifiant le contenu de la page
     */
    public function world() {
        return array(
            '#theme' => 'world',
            '#texte' => $this->t('Hello world !'),
        );

    }

}
 

 

Outre l’usage de namespaces, on remarque que notre classe de contrôleur étend la classe fournie par défaut par Drupal 8 : ControllerBase. Celle-ci donne accès à des méthodes comme t(), qui permet de définir des chaînes traduisibles.

Quant à notre méthode de contrôleur ciblée par la route, elle renvoie un tableau associatif avec deux clés : #theme, qui permet de faire une correspondance avec une entrée dans le hook_theme (que l’on va utiliser ensuite) et #texte, une clé arbitraire qui va nous permettre de passer un contenu variable à notre page.

Création du template

Le lien entre l'action du contrôleur et le template correspondant va se faire en créant une fonction hello_world_theme() dans le fichier hello_world.module (que nous allons créer pour l'occasion) :

function hello_world_theme() {

    return array(
        'world' => array(
            'template' => 'world',
            'variables' => array('texte' => NULL)
        ),
    );

}

On précise ici le template à appeler (world.html.twig, sans besoin de préciser ses extensions) et les variables à injecter dans le template Twig.

Créons celui-ci dans un dossier templates à la racine du module :

Ceci est un texte issu d'une variable : {{ texte }}

L'utilisation des doubles accolades permet d'afficher le contenu d'une variable en Twig. Cette variable sera automatiquement sécurisée pour contrer les failles XSS. Bien entendu, nous pouvons utiliser des balises HTML dans notre template.

Après avoir éventuellement vidé le cache, on obtient bien l'affichage de notre page en se rendant sur l'url <racine>/hello :

mod_drupal2

 

Création du lien de menu

L'URL que nous avons défini n'est pas forcément connue des utilisateurs du site : il peut être utile de la rendre disponible dans un menu et, plutôt que de devoir passer par le backoffice, nous pouvons le faire directement dans le code via un fichier de configuration yml (et non via le hook_menu() comme dans Drupal 7).

Il suffit pour ce faire de créer le fichier hello_world.links.menu.yml à la racine du module et d'y écrire le code suivant :


Après avoir vidé le cache, un lien vers notre page apparaîtra sur le menu principal (nous avons affecté notre lien de menu à ce dernier via la propriété menu_name). La propriété description est tout à fait facultative : elle permet de remplir l'attribut title du lien.

 

Conclusion

Nous avons vu que créer un module très simple avec Drupal 8 requiert diverses manipulations et une architecture rigoureuse. Si cela peut paraître long, cette organisation ciselée permettra dans le cas de projets réels et complexes une meilleure maintenabilité du code.

2 commentaires

  1. J’apprécie beaucoup ton tuto pour se lancer dans drupal et les modules.
    Il y a juste une coquille dans le dernier bout de code, il manque les guillemets pour le title et la description.

    Bien à toi

  2. Un grand merci pour ce tuto très ciblé. Je voulais juste savoir comment communiquent les contrôleurs et les Templates. J’été influencé par la méthode de symfony. En moins d’une minute votre tuto a répondu à ma question.
    merci encore

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.