Créer un module Magento 2 peut sembler complexe au premier abord, mais en suivant une méthodologie structurée, vous verrez que c'est accessible. Dans ce guide complet, je vous accompagne étape par étape dans la création d'un module fonctionnel.
1. Structure de base d'un module
Tout module Magento 2 doit respecter une structure de fichiers précise. Voici l'arborescence minimale :
app/code/Vendor/ModuleName/
├── etc/
│ └── module.xml
├── registration.php
└── composer.json (optionnel mais recommandé)Remplacez Vendor par votre nom d'entreprise et ModuleName par le nom de votre module.
2. Fichiers obligatoires
registration.php
Ce fichier enregistre votre module auprès de Magento :
<?php
/**
* @category Vendor
* @package Vendor_ModuleName
*/
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Vendor_ModuleName',
__DIR__
);etc/module.xml
Ce fichier déclare le module et ses dépendances :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_ModuleName" setup_version="1.0.0">
<sequence>
<!-- Dépendances (modules qui doivent être chargés avant) -->
<module name="Magento_Catalog"/>
</sequence>
</module>
</config>3. Créer un Controller
Les controllers gèrent les requêtes HTTP. Voici comment créer une page frontend accessible via /modulename/index/index :
etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="modulename" frontName="modulename">
<module name="Vendor_ModuleName"/>
</route>
</router>
</config>Controller/Index/Index.php
<?php
declare(strict_types=1);
namespace Vendor\ModuleName\Controller\Index;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\View\Result\Page;
class Index implements HttpGetActionInterface
{
/**
* @var PageFactory
*/
private PageFactory $pageFactory;
/**
* @param PageFactory $pageFactory
*/
public function __construct(PageFactory $pageFactory)
{
$this->pageFactory = $pageFactory;
}
/**
* Execute action
*
* @return Page
*/
public function execute(): Page
{
$page = $this->pageFactory->create();
$page->getConfig()->getTitle()->set(__('Ma Page Custom'));
return $page;
}
}4. Injection de dépendances (DI)
Magento 2 utilise l'injection de dépendances via le constructeur. Le fichier etc/di.xml permet de configurer les dépendances :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- Préférence : remplacer une interface par une implémentation -->
<preference for="Vendor\ModuleName\Api\ServiceInterface"
type="Vendor\ModuleName\Model\Service"/>
<!-- Type : configurer les arguments d'un constructeur -->
<type name="Vendor\ModuleName\Model\MyClass">
<arguments>
<argument name="config" xsi:type="array">
<item name="key" xsi:type="string">value</item>
</argument>
</arguments>
</type>
</config>5. Créer un Model avec ResourceModel
Pour stocker des données en base, vous avez besoin de trois classes :
Model/Item.php (Model)
<?php
declare(strict_types=1);
namespace Vendor\ModuleName\Model;
use Magento\Framework\Model\AbstractModel;
use Vendor\ModuleName\Model\ResourceModel\Item as ResourceModel;
class Item extends AbstractModel
{
/**
* @var string
*/
protected $_eventPrefix = 'vendor_modulename_item';
/**
* Initialize resource model
*
* @return void
*/
protected function _construct(): void
{
$this->_init(ResourceModel::class);
}
}Model/ResourceModel/Item.php (ResourceModel)
<?php
declare(strict_types=1);
namespace Vendor\ModuleName\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Item extends AbstractDb
{
/**
* @var string
*/
protected $_eventPrefix = 'vendor_modulename_item_resource';
/**
* Initialize resource model
*
* @return void
*/
protected function _construct(): void
{
$this->_init('vendor_modulename_item', 'entity_id');
}
}Model/ResourceModel/Item/Collection.php (Collection)
<?php
declare(strict_types=1);
namespace Vendor\ModuleName\Model\ResourceModel\Item;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Vendor\ModuleName\Model\Item as Model;
use Vendor\ModuleName\Model\ResourceModel\Item as ResourceModel;
class Collection extends AbstractCollection
{
/**
* @var string
*/
protected $_eventPrefix = 'vendor_modulename_item_collection';
/**
* Initialize collection
*
* @return void
*/
protected function _construct(): void
{
$this->_init(Model::class, ResourceModel::class);
}
}6. Script d'installation de la base de données
Créez la table via un script de schema :
etc/db_schema.xml
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="vendor_modulename_item" resource="default" engine="innodb"
comment="Module Items Table">
<column xsi:type="int" name="entity_id" unsigned="true" nullable="false"
identity="true" comment="Entity ID"/>
<column xsi:type="varchar" name="name" nullable="false" length="255"
comment="Item Name"/>
<column xsi:type="text" name="description" nullable="true"
comment="Description"/>
<column xsi:type="smallint" name="is_active" unsigned="true"
nullable="false" default="1" comment="Is Active"/>
<column xsi:type="timestamp" name="created_at" nullable="false"
default="CURRENT_TIMESTAMP" comment="Created At"/>
<column xsi:type="timestamp" name="updated_at" nullable="false"
default="CURRENT_TIMESTAMP" on_update="true" comment="Updated At"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="entity_id"/>
</constraint>
</table>
</schema>7. Créer un Block et un Template
Block/ItemList.php
<?php
declare(strict_types=1);
namespace Vendor\ModuleName\Block;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Vendor\ModuleName\Model\ResourceModel\Item\CollectionFactory;
class ItemList extends Template
{
/**
* @var CollectionFactory
*/
private CollectionFactory $collectionFactory;
/**
* @param Context $context
* @param CollectionFactory $collectionFactory
* @param array $data
*/
public function __construct(
Context $context,
CollectionFactory $collectionFactory,
array $data = []
) {
parent::__construct($context, $data);
$this->collectionFactory = $collectionFactory;
}
/**
* Get active items
*
* @return \Vendor\ModuleName\Model\ResourceModel\Item\Collection
*/
public function getItems()
{
return $this->collectionFactory->create()
->addFieldToFilter('is_active', 1);
}
}view/frontend/layout/modulename_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Vendor\ModuleName\Block\ItemList"
name="modulename.item.list"
template="Vendor_ModuleName::item/list.phtml"/>
</referenceContainer>
</body>
</page>view/frontend/templates/item/list.phtml
<?php
/**
* @var \Vendor\ModuleName\Block\ItemList $block
*/
$items = $block->getItems();
?>
<div class="modulename-items">
<?php if ($items->getSize()): ?>
<ul class="items-list">
<?php foreach ($items as $item): ?>
<li class="item">
<h3><?= $block->escapeHtml($item->getName()) ?></h3>
<p><?= $block->escapeHtml($item->getDescription()) ?></p>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p><?= __('No items found.') ?></p>
<?php endif; ?>
</div>8. Activer et tester le module
Une fois tous les fichiers créés, activez le module :
# Activer le module
bin/magento module:enable Vendor_ModuleName
# Mettre à jour la base de données
bin/magento setup:upgrade
# Compiler le code (mode production)
bin/magento setup:di:compile
# Nettoyer le cache
bin/magento cache:clean9. Structure complète du module
Voici l'arborescence finale de notre module :
app/code/Vendor/ModuleName/
├── Block/
│ └── ItemList.php
├── Controller/
│ └── Index/
│ └── Index.php
├── etc/
│ ├── db_schema.xml
│ ├── di.xml
│ ├── module.xml
│ └── frontend/
│ └── routes.xml
├── Model/
│ ├── Item.php
│ └── ResourceModel/
│ ├── Item.php
│ └── Item/
│ └── Collection.php
├── view/
│ └── frontend/
│ ├── layout/
│ │ └── modulename_index_index.xml
│ └── templates/
│ └── item/
│ └── list.phtml
├── composer.json
└── registration.phpConclusion
Vous avez maintenant les bases pour créer un module Magento 2 complet. Les points clés à retenir :
- Respectez toujours la structure de fichiers imposée par Magento
- Utilisez l'injection de dépendances via le constructeur
- Préférez les interfaces aux classes concrètes
- Utilisez
db_schema.xmlpour les modifications de base de données - N'oubliez pas de vider le cache après chaque modification
Pour aller plus loin, explorez les concepts avancés comme les Plugins, les Observers, les API REST et GraphQL. N'hésitez pas à me contacter pour un accompagnement sur vos projets Magento 2 !