PrestaShop 9 marque un virage architectural majeur. Avec le passage à Symfony 6.4 LTS et PHP 8.1 minimum, les règles du jeu changent pour les développeurs de modules. L'injection de dépendances devient la norme, les contrôleurs sont des services, et la nouvelle Admin API ouvre des possibilités inédites. Voici ce qu'il faut savoir pour développer un module PS 9 dans les règles de l'art.
Le changement de paradigme : tout est service
Dans PrestaShop 8, on pouvait encore s'en sortir avec des classes PHP classiques, des méthodes statiques et des appels directs au container. En PS 9, cette approche est obsolète.
Chaque composant de votre module — contrôleurs, services métier, repositories — doit être déclaré dans un fichier config/services.yml et recevoir ses dépendances par injection de constructeur. Plus de $this->get('service_name') dans les contrôleurs, plus d'instanciation manuelle avec new MonService().
Concrètement, un contrôleur admin PS 9 ressemble à ça : il étend FrameworkBundleController, reçoit ses services dans le constructeur, et utilise les attributs PHP 8 pour le routing (#[Route]). C'est plus propre, plus testable, et surtout plus maintenable.
Structure d'un module PS 9
La structure de fichiers évolue pour refléter l'architecture Symfony. Un module PS 9 bien organisé contient les éléments suivants.
Le fichier principal monmodule.php reste le point d'entrée : il déclare le module, ses hooks, et ses méthodes d'installation. Mais la logique métier n'y réside plus — elle est dans les services.
Le répertoire config/ contient services.yml (déclaration des services) et éventuellement routes.yml (ou les attributs PHP dans les contrôleurs). C'est le cœur de l'intégration Symfony.
Le répertoire src/ contient les contrôleurs (Controller/), les services métier (Service/), les entités Doctrine si nécessaire (Entity/), et les commandes CLI (Command/).
Le répertoire views/ contient les templates Twig pour le back-office et Smarty pour le front-office (PS 9 conserve Smarty pour le front).
L'injection de dépendances en pratique
Le fichier config/services.yml est la pièce maîtresse. Vous y déclarez chaque service avec ses arguments :
Votre service principal reçoit le EntityManagerInterface, la Configuration PrestaShop, et tout autre service dont il a besoin — directement dans le constructeur. Plus besoin d'aller chercher les dépendances dans un container global.
Les avantages sont concrets : chaque service a un contrat clair (ses dépendances sont visibles dans le constructeur), les tests unitaires deviennent simples (on injecte des mocks), et le container Symfony optimise automatiquement l'instanciation (lazy loading).
La nouvelle Admin API
PrestaShop 9 introduit une Admin API moderne basée sur API Platform. Elle remplace progressivement l'ancien Webservice API et expose les ressources au format JSON-LD avec des conventions REST strictes.
Pour un développeur de modules, l'intérêt est double. D'abord, vous pouvez consommer l'API depuis des outils externes (ERP, CRM, applications mobiles) avec une authentification OAuth2 et des scopes granulaires. Ensuite, vous pouvez étendre l'API en déclarant vos propres ressources avec les annotations ApiResource sur vos entités Doctrine.
L'API supporte nativement la pagination, le filtrage, le tri, et la sérialisation/désérialisation des relations. C'est un gain de productivité considérable par rapport à l'ancien Webservice qui nécessitait du XML et des manipulations manuelles.
Migration Swift Mailer → Symfony Mailer
PrestaShop 9 remplace Swift Mailer (abandonné) par Symfony Mailer. Si votre module envoie des emails, le changement est obligatoire. L'API est similaire mais pas identique : les classes changent (Symfony\Component\Mime\Email remplace Swift_Message), et la configuration du transport se fait via le DSN Symfony.
Le bon réflexe est de créer un service d'envoi d'email dans votre module qui abstrait le composant Mailer. Si vous devez supporter à la fois PS 8 et PS 9, ce service peut détecter la version et utiliser la bonne librairie.
Composer et la gestion des dépendances
PS 9 s'appuie pleinement sur Composer pour la gestion des dépendances. Votre module doit avoir un composer.json qui déclare ses dépendances PHP et ses autoloaders. L'autoloading PSR-4 est la norme : chaque classe dans src/ est automatiquement chargée selon son namespace.
Attention aux conflits de versions. Si votre module utilise Guzzle 7 et qu'un autre module utilise Guzzle 6, Composer ne pourra pas résoudre les dépendances. La bonne pratique : préfixer vos dépendances avec PHP-Scoper ou utiliser les composants Symfony déjà présents dans PrestaShop plutôt que d'en ajouter de nouveaux.
Les bonnes pratiques PS 9
CQRS — PrestaShop 9 utilise le pattern Command/Query pour séparer les lectures (Query) des écritures (Command). Vos modules devraient suivre cette convention pour les opérations complexes : un CreateOrderCommand plutôt qu'un appel direct à l'ObjectModel.
Typage strict — Activez declare(strict_types=1) dans tous vos fichiers PHP. Typez les arguments, les retours, et les propriétés. PHP 8.1 propose les enums, les fibres, et les types d'intersection — utilisez-les quand c'est pertinent.
Tests — PHPUnit pour les tests unitaires, Behat ou PrestaFlow pour les tests fonctionnels. Un module sans tests est un module qui cassera à la prochaine mise à jour de PrestaShop.
SOLID — Responsabilité unique, interfaces claires, dépendances abstraites. Ces principes ne sont plus optionnels en PS 9 : l'architecture Symfony les impose naturellement via l'injection de dépendances.
Besoin d'un module PrestaShop 9 ?
Module sur-mesure, migration PS 8 → PS 9, ou formation technique — je vous accompagne sur vos projets PrestaShop Symfony.
Demander un devis gratuit