Initiation au développement de module custom sur Drupal 8

02 JulDrupalCMS

Avec l’ajout de Symfony, Drupal 8 introduit un changement important dans le développement des modules custom.

Sous Drupal 8, le dossier modules se trouve à la racine de votre installation Drupal et non dans le dossier /sites/all/modules comme c’était le cas sur Drupal 7. 

Dans un premier temps, nous allons créer un répertoire “custom” dans le dossier “modules”. Ce dernier rassemblera l’ensemble de vos modules custom. Ensuite nous allons créer un deuxième répertoire dans le dossier custom. Le nom de ce dossier est le nom dit “machine” de votre module custom. Il doit être unique, en minuscule et sans espace.

Le chemin de votre module custom doit être /modules/custom/mon_module.


Dans un premier temps, nous allons créer un répertoire “custom” dans le dossier “modules”. Ce dernier rassemblera l’ensemble de vos modules custom. Ensuite nous allons créer un deuxième répertoire dans le dossier custom. Le nom de ce dossier est le nom dit “machine” de votre module custom. Il doit être unique, en minuscule et sans espace.

Le chemin de votre module custom doit être /modules/custom/mon_module.

Si votre module custom a vocation à être publié sur drupal.org (et ainsi éviter les soucis de concordance entre deux modules de même nom), vous pouvez vérifier que le nom choisi n’existe pas en vérifiant que la page https://www.drupal.org/project/mon_module n’existe pas.

Par la suite nous verrons comment :

  • Créer une route avec le système de routing proposé par Symfony
  • Créer une page avec un contrôleur
  • Créer un lien de menu vers notre page
  • Créer et instanciation un service
  • Utiliser l’injection de dépendance
  • Créer un bloc via un plugin
  • Stocker et récupérer des variables via Drupal Config
  • Créer un formulaire accessible depuis le back-office

1. Création du module custom

La première étape pour la création d’un module custom sous Drupal 8 est la création d’un fichier “mon_module.info.yml”. Autrement appelé mon_module.info sous Drupal 7. En effet, Drupal 8 utilise le format YAML.

Dans notre fichier .info.yml, nous allons insérer le code suivant :

Code Mon Module

La propriété name définit le nom du module, core la version de Drupal nécessaire au bon fonctionnement et type indique que nous sommes en train de créer un module.

La propriété description permet d’ajouter une description à votre module et la propriété package permet de regrouper votre module sous le nom “Mes modules”.

A ce stade, votre module ne fait rien mais s’affiche désormais dans la liste des modules.

Module Custom D8

Il est également possible de créer un fichier mon_module.module afin d’utiliser les différents hooks disponible sur drupal 8.

En résumé votre module custom :

  1. Doit avoir un nom “machine” unique, en minuscule et sans espace.
  2. Doit être créé dans le répertoire modules/custom.
  3. Doit contenir au minimum le fichier .info.yml décrivant le titre du module, la version du core de Drupal 8 et le type.

2. Création d’une route

Une route est une notion de Symfony associée au système de routing. Cela permet de créer des URLs comme /mon-module, /ma-page, /bonjour,... et de leur associer un contrôleur Symfony qui va nous permettre de bâtir le contenu de la page.

Plus d’informations sur le routing dans la documentation officielle de Symfony.

Nous allons maintenant créer le fichier « mon_module.routing.yml » avec le code suivant :

Mon Modulerouting.yml
  • La première ligne indique la clé unique de la route.
  • La propriété “path” définit l’url de la page que nous allons créer.
  • La propriété “défauts” définit les données par défaut de notre route. Dans notre exemple, nous ajoutons l’appel à un contrôleur.
  • La propriété “requirements” définit les règles obligatoires d’accès pour pouvoir utiliser notre route.

Pour l’instant, le contrôleur “MaPageController” n’existe pas. Si nous tentons d’accéder à l’url /ma-page, une erreur s’affiche.

 

3. Création d’un contrôleur

Lors de la création de notre route, nous avons mandaté la création du contenu de notre page à la méthode maPage du contrôleur MaPageController. Ceci est définie via la ligne ci-dessous.

Module Controller

Nous allons maintenant créer un fichier MaPageController.php et le placer dans le répertoire suivant : modules/custom/mon_module/src/Controller/MaPageController.php

Dans notre cas, le contrôleur est une classe du nom MaPageController (attention à bien respecter la nomenclature du “camel case” . Cela signifie que la première lettre de chaque mot doit être en majuscule. Le nom du controller doit également se terminer par Controller. Exemple : MaPageController)

Après avoir créé notre nouveau fichier, entrez le code suivant :

Page Controller

Nous remarquons dans ce code, que nous définissons bien notre contrôleur avec la classe MaPageController qui implémente la classe ControllerBase.

Avec le ControllerBase, il est possible d’utiliser la fonction de traduction t()

Controller Base Traduction

Une fois sauvegardé, rendez-vous sur la page /ma-page.

Titre page

4. Création d’un lien

Sous Drupal 7, la création d’un lien de menu custom se faisait via un hook_menu(). Sous Drupal 8, la création d’un lien de menu est désormais possible via une configuration YAML.

Comme pour les étapes précédentes, nous allons créer un fichier nommé “mon_module.links.menu.yml”.

Insérez le code suivant :

Ma Page Module

Dans ce fichier, vous pouvez définir l’ensemble des liens de menu de votre module custom. Il suffit de les définir les uns en dessous des autres.

  • La première ligne indique la clé unique pour le lien.
  • La propriété “title” définit le titre du lien (requis.
  • La propriété “description” permet d’ajouter une description au menu (optionnel.
  • La propriété “route_name” indique la route à appeler lors du clic sur le lien.
  • Il est possible d’y ajouter plusieurs propriétés optionnelles (parent, weight,...)

Afin d’activer notre lien de menu, pensez à vider les caches. Action possible via drush ou via le back-office de drupal (/admin/config/development/performance.

Menu

5. Création d'un service

Un service est une classe qui propose des fonctionnalités spécifiques et globales à l’ensemble du projet. La méthode d'instanciation d’un service se fait via un Service Container. Celui-ci s’occupe de la création et de l'initialisation de l'objet.

Sous Drupal 7, pour appeler une fonction d’un autre module, nous aurions utilisé la fonction module_invoke. Avec Drupal 8 et l’adoption du concept de Service Container basée sur le Symfony, il suffit d’utiliser l’injection de dépendance afin que l’utilisation soit transparente pour l’utilisateur du service.

Nous allons maintenant déclarer un service dans notre module “mon_module”. Pour cela, il faut créer un fichier mon_module.services.yml avec le code suivant :

Module Service

Ensuite, nous allons déclarer notre classe “Date” dans le répertoire suivant : modules/custom/mon_module/src/Service/Date.php

Module Date

Dans notre exemple, nous venons d’ajouter une fonction permettant de récupérer le nombre de jours entre deux dates

Pour utiliser un service dans un module, il suffit de l’appeler en utilisant le Service Container de Drupal

Date Service

Le Service Container va alors instancier l’objet, l’initialiser et le renvoyer. Maintenant, il suffit de l’utiliser pour appeler la fonction differenceDate()

Different Date

En résumé et de la même façon, il est possible d’appeler un service du core de Drupal

Add Core Drupal

6. Injection de dépendance

Afin d’éviter la répétition de l’appel au Service Container de Drupal, il suffit d’étendre la classe ControllerBase pour ainsi retrouver les services dans la méthode “create” du contrôleur. Ci-dessous un exemple de contrôleur avec une injection de dépendance du service Date précédemment créé.

Extend Controller Base

 

7. Création d’un plugin

Sous Drupal 8, un plugin a pour vocation de remplacer les différents hook_xxx_info() de Drupal 7 et de leurs hook respectifs (block, form, view,...) sous une approche orientée objet.

Nous allons créer un block en utilisant le système de plugin fourni par Drupal 8.

Commençons par créer un fichier MonBlock.php dans le répertoire : /modules/custom/mon_module/src/Plugin/Block

Dans ce fichier, nous allons créer une classe qui étends la classe BlockBase de Drupal 8.

Block Plugin

 

Dans ce code, plusieurs fonctions :

  • build() : Permet de gérer le contenu afficher dans le bloc. Ici nous affichons la phrase “Voici ma date de naissance : 2020-26-04” .
  • blockForm() : Permet d’ajouter un formulaire lors de modification du bloc depuis le back-office.
  • blockSubmit() : Permet d’exécuter du code lorsqu’on clique sur le bouton enregistrer lors de la modification du bloc depuis le back-office.

Il est important de noter et de respecter le commentaire au-dessus de la déclaration de la classe :

Commentaire

id : Identifiant unique du bloc admin_label : Nom du bloc depuis le back-office category : Catégorie du bloc. Permet de regrouper plusieurs blocs sous la même catégorie.

Afin d’activer le nouveau bloc, pensez à vider les caches. Action possible via drush ou via le back-office de drupal (/admin/config/development/performance).

Notre nouveau bloc apparaît dans la liste des blocs depuis le back-office.

Block Back Office

8. Variables de configuration du module custom

Depuis Drupal 8, il est possible d’ajouter des variables de configuration qui s’initialise lors de l’activation du module. Une fois activé, ces variables peuvent être récupérer et modifier.

Pour pouvoir utiliser les variables de configuration, il faut créer un fichier nommé “dates.settings.yml” dans le dossier “mon_module/config/install”.

Dans ce fichier, nous allons déclarer une variable :

Date Naissance

Pour récupérer cette variable, il faut utiliser la méthode get :

Variable date

Pour modifier cette variable, il faut utiliser la méthode set :

Methode Set

Il est possible de rendre administrable cette configuration via l’utilisation des formulaires de configuration Drupal en créant une classe qui étend la classe “ConfigFormBase” de Drupal 8.

 

9. Création d’un formulaire

Dans cette partie, nous allons voir comment créer un formulaire accessible depuis le back-office.

Dans un premier temps, nous allons créer un fichier MonForm.php dans /modules/custom/mon_module/src/Form/ avec le code suivant : 

Mon Formulaire

Voici les méthodes à ajouter dans notre classe “MonForm” :

getEditableConfigNames() : Permet d’obtenir le nom de la configuration

Editable Config

getFormId() : Retourne le nom unique du formulaire

 Get Rid ID

buildForm() : Retourne le formulaire

 Build Form

validateForm() : Exécuter lors de la validation du formulaire
submitForm() : Exécuter lors de la soumission du formulaire

Submit Form

Pour récupérer et utiliser les données du formulaire et ainsi récupérer la valeur du champ “bienvenue_message”, il faut appeler la config avec son identifiant :

Bienvenue Message

10. Mettre à jour le module custom vers Drupal 9

Drupal 9 étant construit sur Drupal 8, le principe de compatibilité des modules customs est similaire. La méthode de mise à jour est simple. Le module custom doit être scanné par le module contrib “Status Upgrade” afin de vérifier la qualité du code.

Après analyse, le module “Status Upgrade” identifie les erreurs qui nécessitent d’être corrigées avant mise à jour.

Plus d’information sur https://blog.actency.fr/drupal/sortie-drupal-9-et-mise-a-jour-depuis-Drupal-8 et https://www.drupal.org/project/upgrade_status

Pour plus d’information sur le statut de dépréciation d’un module il est possible de consulter cette page : https://dev.acquia.com/drupal9/deprecation_status

Partagez toute l'actualité

Partagez sur Facebook Partagez sur Twitter Copier le lien

Populaires

À la une

Découvrir plus de workshop technologiques

Image
Une_usine_a_sites_Drupal_workshop_Actency
Webinar

Une usine à sites avec Drupal, pourquoi ?

  • 4 November 2020
    09:30 - 10:00
Image
Savoir_gerer_un_projet_drupal_agile
Webinar

Savoir gérer un projet Drupal en méthode Agile

  • 6 November 2020
    11:30 - 12:00
Image
REX_refonte_de_mutuelles_workshop_Actency
Webinar

REX Refonte de Mutuelles sur Drupal : Difficultés et Solutions

  • 4 November 2020
    09:30 - 10:00
Image
Les_defis_de_intégration_Drupal_workshop_Actency
Webinar

Les défis de l'intégration Drupal dans un SI complexe

  • 23 Octobre 2020
    09:30 - 10:00
Image
Demystifions_l_agile
Webinar

Démystifions l'Agile

  • 5 November 2020
    11:30 - 12:00
Image
Workshop Actency Strasbourg Paris Toulouse Lyon Bordeaux Nouvelle Orléans
Webinar

Exploitez les dernières innovations dans une usine à sites

  • 4 November 2020
    11:30 - 12:00
Image
Solution_headless_drupal_workshop_Actency
Webinar

Solution headless Drupal : outil d’intégration d’informations dans le content workflow

  • 11 November 2020
    09:30 - 10:00