Logo de Béjean Développement

L'arborescence d'un module Magento 2

Dans un précédent article, nous avons étudiés les bases d'un module Magento 2. Dans cet article, nous allons expliquer l'arborescence d'un module.

Les dossiers et fichiers de base

Pour cet article, j'ai cloné le dépôt de mon modèle de base dans le dossier app/code/NicolasBejean/Master.

Une fois le dépôt cloné, vous devez avoir l'arborescence suivante :

.
├─ app/
|  └─ code/
|     └─ NicolasBejean/
|        └─ Master/
|           └─ etc/
|              └─ module.xml
|           └─ .gitignore
|           └─ .gitlab-ci.yml
|           └─ CHANGELOG.md
|           └─ LICENCE
|           └─ README.md
|           └─ composer.json
|           └─ registration.php

Dans ce dossier, les éléments obligatoires sont etc/module.xml, composer.json et registration.php. Voici une brève explication des autres fichiers que j'ai intégrés à mon module de base :

  • .gitignore : Quand je développe un module, je lui crée un dépôt Git. Ce fichier me permet de spécifier les fichiers que je souhaite ignorer dans le dépôt du module. Lien vers la documentation Git.
  • .gitlab-ci.yml : Pour mettre en place une CI/CD, j'utilise Gitlab CI. Ce fichier est donc très utile pour tester et déployer mon module. Un article sera prochainement consacré au test et au déploiement d'un module Magento 2.
  • CHANGELOG.md : Un module évolue constamment. Il est donc important de noter les changements réalisés au fur et à mesure que des versions sont créées. Pour cela, j'utilise ce fichier en me basant le plus possible sur ce modèle.
  • LICENCE : L'ensemble des modules que je développe personnellement sont sous licence GNU GPL 3.
  • README.md : Ce fichier est présent pour présenter, expliquer le module et ses fonctionnalités.

Les dossiers que l'on peut retrouver

Suivant les fonctionnalités de notre module, nous allons avoir une arborescence différente. Un module peut donc avoir une multitude de dossiers :

.
├─ app/
|  └─ code/
|     └─ NicolasBejean/
|        └─ Master/
|           └─ Api/
|           └─ Block/
|           └─ Console/
|           └─ Controller/
|           └─ Cron/
|           └─ CustomerData/
|           └─ etc/
|           └─ Helper/
|           └─ i18n/
|           └─ Model/
|           └─ Observer/
|           └─ Plugin/
|           └─ Setup/
|           └─ Test/
|           └─ Ui/
|           └─ view/
|           └─ ViewModel/

Le dossier Api

Le dossier Api va comporter l'ensemble des interfaces ainsi que leurs implémentations. Chaque interface est déclarée dans le fichier di.xml du dossier etc comme une preference, par exemple :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation=&quot urn:magento:framework:ObjectManager/etc/config.xsd">
    ...
    <preference for="NicolasBejeanContentManagerApiDataContentManagerInterface" type="NicolasBejeanContentManagerModelContentManager" />
    ...
</config>

La classe PHP ...\Model\ContentManager implémente l'interface ...\Api\Data\ContentManagerInterface. L'implémentation d'une interface nécessite d'être renseignée dans le fichier di.xml car Magento 2 utilise l'injection de dépendances comme modèle de conception.

Voici le lien vers la documentation des interfaces publics et des API de Magento 2 ainsi que le lien vers la documentation PHP sur les interfaces.

Les dossiers Block, Controller et Model

Magento 2 utilise le modèle de conception (Design Pattern) MVC, qui signifie Modèle - Vue - Contrôleur.

Le dossier Block contient toutes les classes PHP nécessaires à la vue, le dossier Controller contient toutes les classes PHP nécessaire à la logique et le dossier Model contient toutes les classes permettant d'aller récupérer les informations dans la base de données.

Le dossier Console

Ce dossier va contenir toutes les classes PHP permettant l'utilisation des commandes CLI. Les commandes CLI sont basées le framework Symfony.

Un module peut comporter une multitude de commandes. Chaque commande est définie dans le fichier di.xml du dossier etc, par exemple :

<?xml version="1.0" encoding="utf-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    ...
    <type name="Magento\Framework\Console\CommandListInterface">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="nicolasbejean_rabbitmq_defaultmessage" xsi:type="object">NicolasBejean\RabbitMq\Console\Command\DefaultMessage</item>
            </argument>
        </arguments>
    </type>
    ...
</config>

Dans cet exemple, la commande NicolasBejean\RabbitMq\Console\Command\DefaultMessage est du type Magento\Framework\Console\CommandListInterface. Chaque commande doit être nommée, dans notre exemple : nicolasbejean_rabbitmq_defaultmessage.

Voici le lien vers la documentation des commandes CLI de Magento 2.

Le dossier Cron

Sous Magento 2, les crons utilisent le planificateur de tâches UNIX nommé crontab. Beaucoup de fonctionnalités utilisent les crons : les règles de prix catalogue, l'envoi des emails, la réindexation...

Il est possible de définir un ou plusieurs crons par module. Chaque cron est déclaré dans le fichier crontab.xml du dossier etc, par exemple :

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    ...
    <group id="nicolasbejean">
        <job name="nb_sales_exported_data_order" instance="NicolasBejean\Sales\Cron\ExportOrderData" method="execute">
            <schedule>* * * * *</schedule>
        </job>
    </group>
    ...
</config>

Dans cet exemple, le cron d'exportation de commande nommé nb_sales_exported_data_order exécutera toutes les minutes * * * * * la méthode execute de la classe NicolasBejean\Sales\Cron\ExportOrderData associée au cron.

On remarque également dans l'exemple que le job est défini dans un groupe nommé nicolasbejean. Magento offre la possibilité de créer des groupes de crons. Ces derniers peuvent être configurés différemment des groupes par défaut. De plus, il est possible de créer plusieurs crons par groupe.

Voici le lien vers la documentation des crons et voici le lien vers la documentation des groupes de crons.

Le dossier Helper

Magento ne recommande pas la création de classes, dites d'assistances. Elles sont considérées comme un anti-pattern. Pour Magento, il faut éviter de créer des Helpers.

Voici le lien vers les bonnes pratiques de Magento 2.

Le dossier i18n

Au sein de ce dossier, nous allons retrouver des fichiers CSV contenant les dictionnaires de traduction de votre module. Chaque fichier est nommé dans la langue cible et comporte au minimum 2 colonnes, une première comprenant la clé de traduction et/ou la phrase d'origine et une seconde comprenant la traduction, par exemple :

"Add to cart", "Ajouter au panier"

Dans ce fichier, nous traduisons, en français, la phrase Add to cart par Ajouter au panier. Le fichier de traduction doit se nommer fr_FR.csv.

Voici le lien vers la documentation des fichiers de traduction.

Le dossier Observer

Les observateurs permettent d'étendre les fonctionnalités de Magento 2. Le modèle publication-abonnement est le modèle de conception (Design Pattern) utilisé.

Les événements sont distribués lorsque certaines actions sont déclenchées et les observateurs sont exécutés lorsqu'un événement, sur lequel l'observateur est configuré, est déclenché.

Chaque Observers doit être déclaré dans le fichier events.xml du dossier etc, par exemple :

<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    ...
    <event name="sales_order_save_after">
        <observer name="nicolasbejean_sales_exportorder" instance="NicolasBejean\Sales\Observer\ExportOrder"/>
    </event>
    ...
</config>

Dans cet exemple, la classe NicolasBejean\Sales\Observer\ExportOrder est rattaché à l'événement sales_order_save_after.

Voici le lien vers la documentation des observateurs.

Le dossier Plugin

Un plugin permet d'intercepter le code, en amont, en aval ou autour d'une fonction, en utilisant les méthodes before, after ou around suivi du nom de la méthode ciblée. Le plugin est limité aux fonctions publiques.

Chaque plugin est déclaré dans le fichier di.xml comme une type, par exemple :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    ...
    <type name="Magento\Customer\Model\AccountManagement">
        <plugin name="NicolasBejeanAccountManagement" type="NicolasBejean\Customer\Plugin\AccountManagement" sortOrder="1" disabled="false" />
    </type>
    ...
</config>

Dans l'exemple ci-dessus, le plugin NicolasBejean\Customer\Plugin\AccountManagement nommé NicolasBejeanAccountManagement est configuré pour intercepter le code de la classe Magento\Customer\Model\AccountManagement où il sera possible de modifier le comportement de Magento 2 soit à la création d'un compte client, soit à l'authentification.

Il est possible de créer plusieurs plugins pour un seul type, dans ce cas, il sera nécessaire de les ordonner. De plus, il est possible de les désactiver sans les supprimer.

Voici le lien vers la documentation des plugins.

Le dossier Setup

Depuis la version 2.3 de Magento, le processus d'installation et de mise à jour de la base de données a été revu. Auparavant, il était nécessaire de créer des scripts PHP pour installer ou mettre à jour sa base de données, voir ci-dessous. Désormais, cela est réalisé par le biais de fichiers XML situé dans le dossier etc.

Voici le lien vers la documentation du schéma déclaratif.

Cependant, il est possible que vous ayez un dossier Setup à la racine d'un module. Ce dossier contient les fichiers nécessaires pour définir la structure des tables dans la base de données ainsi que leur configuration que ce soit pour l'installation ou la mise à jour du module. Ces fichiers sont appelés lorsque la commande bin/magento setup:upgrade est exécutée.

Voici le lien vers la documentation du cycle de vie d'un module Magento 2.

Le dossier Test

Magento propose plusieurs stratégies de test pour garantir la qualité du code. Il y a les tests d'intégration, les tests unitaires JS et PHP, les tests statiques et le vérificateur de version sémantique.

Dans ce dossier Test, nous allons principalement retrouver les dossiers Unit, Integration et Mftf.

Les tests unitaires présents dans le dossier Test/Unit permettent de tester et de vérifier que chaque méthode soit bien appelée et que la valeur retournée est bien la valeur attendue.

Les tests d'intégration nécessite un environnement Magento 2 fonctionnelle avec une base de données vierge. Ils permettent de vérifier et de contrôler la comptabilité d'un module dans un environnement complet.

Pour terminer, le dossier Mftf comportera l'ensemble des tests fonctionnels de votre application. Magento Functional Testing Framework est un projet open-source souvent nommé MFTF. Il permet de développer rapidement des tests fonctionnels pour votre application.

Voici le lien vers le guide de tests de Magento 2 et le lien vers la documentation de Magento Functional Testing Framework.

Le dossier Ui

Ce dossier contient l'ensemble des classes des composants de l'interface utilisateur de votre module. On peut retrouver différentes actions dans une liste déroulante située dans une grille de données.

Il existe plusieurs UI Components au sein de Magento 2, voici le lien vers la documentation.

Le dossier ViewModel

Les modèles de vues sont disponibles depuis Magento 2.2. Ils sont à privilégier lorsqu'il est nécessaire d'injecter des fonctionnalités dans des fichiers de rendu.

Voici le lien vers la documentation des View Models.