Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Développez avec PHP pour PrestaShop
  3. Modules
Extrait - Développez avec PHP pour PrestaShop Architecture, personnalisation, thèmes et conception de modules
Extraits du livre
Développez avec PHP pour PrestaShop Architecture, personnalisation, thèmes et conception de modules
5 avis
Revenir à la page d'achat du livre

Modules

Introduction

L’architecture de PrestaShop permet aux développeurs d’ajouter des fonctionnalités aux boutiques existantes par le biais des modules.

Le module PrestaShop est le point central de vos développements.

Il permet notamment de modifier l’existant sans altérer les fichiers sources tout autant que de rajouter une fonctionnalité à part entière.

Un module peut également être rattaché à un thème en tant que dépendance.

Ce point sera vu plus en détail dans le chapitre Thèmes - Fichier de configuration.

Afin de couvrir l’ensemble des points définissant un module et de donner du concret en guise d’exemple, vous serez, à la fin de ce chapitre, à même de développer une nouvelle fonctionnalité de A à Z : un blog.

Organisation des modules

Les modules sont stockés dans le répertoire modules situé à la racine de la boutique. 

Chaque module est contenu dans un dossier qui lui est propre et comporte au minimum un fichier portant le même nom que le dossier.

Le nom d’un module est défini en caractères minuscules et ne peut comporter que des chiffres et des lettres.

Le caractère underscore est toléré mais vivement découragé étant donné qu’il n’est pas compatible avec le système de traduction utilisant les domaines de traduction.

Il sera volontairement exclu de notre utilisation.

Au sein d’un module, on peut également retrouver plusieurs autres éléments.

config

Le dossier config comporte des fichiers nommés services.yml, pouvant être placés à la racine de celui-ci ou au sein d’un dossier admin ou front.

Ces fichiers serviront à déclarer les routes et services utilisés par le module.

On peut également y retrouver le fichier self_config.yml servant à la configuration automatique du module en ligne de commande.

controllers

Les contrôleurs de type legacy sont présents dans ce dossier.

On y retrouve un dossier front et admin, en fonction de la destination du contrôleur.

models

Ensemble des classes relatives à des ObjectModel utilisés au sein...

Composer

L’utilisation de Composer est fortement recommandée et largement répandue dans le développement de modules PrestaShop, notamment pour les modules fournis par la solution en natif.

Celui-ci permet de :

  • charger automatique les classes de votre module ;

  • rajouter des dépendances à votre module.

Voici le fichier composer.json que vous pourriez obtenir durant la conception de votre module :

{ 
  "name": "eni/eniblog", 
  "description": "Module de blog", 
  "license": "MIT", 
  "authors": [ 
    { 
      "name": "Jonathan Danse" 
    } 
  ], 
  "require": { 
    "php": ">=7.2.5" 
  }, 
  "require-dev": { 
    "prestashop/php-dev-tools": "^4.1" 
  }, 
  "autoload": { 
    "psr-4": { 
      "Eni\\Blog\\": "src/" 
    }, 
    "classmap": [ 
      "classes", ...

Classe principale

Avant de pouvoir définir la classe principale d’un module, il est nécessaire de lui attribuer un nom qui lui est propre et qui est unique.

Dans le cadre de cet ouvrage et afin de constituer un module couvrant l’ensemble des aspects que vous allez voir dans ce chapitre, la fonctionnalité que vous réalisez est un blog.

De ce fait, le module s’appelle eniblog.

Votre classe principale se nomme à son tour eniblog.php et est située dans le dossier /modules/eniblog/.

Veillez toujours à préfixer vos noms de modules afin de ne pas rentrer en conflit avec un module implémentant la même fonctionnalité.

1. Test préalable

Un module s’articulant sur la structure MVC (modèle-vue-contrôleur) de PrestaShop, il est important que les fichiers PHP de celui-ci ne soient pas exécutables en dehors de celle-ci.

Afin de réaliser ce test, il est possible de s’appuyer sur la valeur de la constante PS_VERSION, qui est toujours définie en début d’initialisation par PrestaShop. 

Cette vérification peut se faire de la sorte :

<?php 
if (!defined('_PS_VERSION_')) { 
    exit; 
} 

2. Héritage

La classe principale de votre module doit étendre la classe Module afin d’être reconnue comme telle.

Ainsi, la classe principale du module est nommée eniblog et étend donc la classe Module. L’usage du camel case est suggéré mais non obligatoire, il est avant tout utile à la lecture.

Le fichier eniblog.php situé dans le répertoire /modules/eniblog contient ceci :

<?php 
declare(strict_types=1); 
 
if (!defined('_PS_VERSION_')) { 
    exit; 
} 
 
class eniblog extends Module 
{ 
    public function __construct() 
    { 
        $this->name...

Installation et désinstallation

La classe Module expose par défaut deux méthodes servant à l’installation et la désinstallation d’un module : install() et uninstall().

1. Méthode install()

Cette méthode est appelée par PrestaShop lors de l’installation d’un module.

Elle permet de définir une série d’actions à réaliser par défaut lors de l’installation, comme l’ajout de tables, de variables de configuration ou encore l’enregistrement de points d’accroche de votre module.

public function install() 
{ 
    return 
        parent::install() 
        // Enregistrement des points d'accroche 
        // Traitement des tables pour la base de données 
        && Configuration::updateValue('ENIBLOG_NB_ARTICLES', 10); 
} 

L’enregistrement des points d’accroche (hooks) doit se réaliser après l’appel à la méthode parente.

Par défaut, cette méthode procède également à l’installation des surcharges (vues au sein du chapitre Pour aller plus loin).

Lors de son déroulement, deux hooks sont appelés :

  • actionModuleInstallBefore : en tout début de processus.

  • actionModuleInstallAfter : en toute fin de processus.

2. Méthode uninstall()

Lorsqu’un module est en cours de désinstallation, la méthode uninstall() est appelée par PrestaShop.

Celle-ci permet notamment à votre module de procéder à une série d’actions pour, par exemple, supprimer les tables ou variables de configuration ajoutées à l’installation du module.

public function uninstall() 
{ 
    return ...

Configuration du module

Lors de l’installation du module, celui-ci a rajouté une valeur de configuration ENIBLOG_NB_ARTICLES avec la valeur par défaut définie sur 10.

Afin de pouvoir modifier cette valeur, il est désormais nécessaire d’ajouter une page de configuration au module. Les configurations ajoutées n’étant pas rattachée au module et les besoins de configuration d’un module pouvant être nombreux, il n’existe pas de solution automatisée.

Pour ce faire, il existe deux possibilités :

  • L’utilisation d’une page spécifique au module, autrement dit un contrôleur spécifique.

  • Une page de configuration accessible par le biais du bouton Configurer en regard du module dans le gestionnaire des modules.

L’ajout d’une page spécifique sera vu en détail dans la section Contrôleurs de ce chapitre.

Lorsque la configuration d’un module permet uniquement la gestion de quelques options, il est usuel de rajouter une simple page accessible par le gestionnaire de modules afin que l’utilisateur final retrouve directement l’édition des paramètres de votre module.

Pour ce faire, la méthode getContent() est utilisée.

Sa seule déclaration suffit à PrestaShop pour afficher le bouton Configurer dans le gestionnaire de modules.

<?php 
 
class EniBlog extends Module 
{ 
    public function getContent() 
    { 
         // L'existence de cette méthode, même vierge de code,  
fait apparaître le bouton "Configurer". 
    } 
} 
images/03EI06.png

1. Effectuer un rendu

Lorsque vous allez consulter la page qui se trouve derrière le bouton Configurer, le rendu est vide de contenu.

images/03EI07.png

La méthode getContent() attend en retour une chaîne de caractères et se charge de restituer celle-ci au navigateur.

public function getContent() 
{ 
    return 'Page de configuration'; 
} 
images/03EI08.png

Étant donné qu’un template Smarty compilé est à son tour une chaîne de caractères, il est également possible de restituer celui-ci en tant que rendu.

public function getContent() 
{ 
    return $this->context->smarty-> ...

Hooks

1. Préambule

Les points d’accroche - autrement nommés hooks - sont des portes ouvertes à l’affichage d’un module à un endroit prédéfini ou encore à l’exécution d’une action à un moment donné.

Les hooks d’action tels que actionCartSave ou encore actionCategoryDelete sont déclenchés lorsqu’une action précise se déroule.

Les hooks d’affichage (display) tels que displayFooter ou displayHome permettent quant à eux de venir placer du code (HTML, mais également JavaScript ou CSS) sur la partie visible, aussi bien en front-office que back-office. 

Enfin, divers hooks comme moduleRoutes ou actionDispatcher permettent de modifier le système natif sans en altérer ses fichiers.

L’utilisation des points d’accroche est plus largement vue dans le chapitre Au cœur de PrestaShop - Hooks.

2. Alias

Les alias permettent d’utiliser l’ancien nom d’un hook lorsque celui-ci change de nom au sein du code principal de PrestaShop.

Pour exemple, le nom du hook displayHeader remplace le hook header.

Il est donc possible d’utiliser les deux noms indifféremment.

L’utilisation d’un alias est dépréciée sous PrestaShop 8 et un avertissement de dépréciation (E_USER_DEPRECATED) est lancé.

3. Enregistrement d’un hook

Positionner un module sur un point d’accroche peut se faire à tout moment, tant que ce dernier est installé.

Via le code

Dans un contexte...

Widgets

L’utilisation de points d’accroche prédéfinis par un module empêche toute liberté quant à l’affichage d’éléments issus du module à l’endroit souhaité par le marchand.

En guise d’exemple, imaginez que votre module de blog donne la possibilité d’afficher un encart avec une liste des derniers articles rédigés.

Dans votre conception, vous allez prendre en considération l’ensemble des points d’accroche dont vous avez connaissance et pour lesquels il vous semble tout à fait adéquat de faire figurer votre module.

Toutefois, certains thèmes sont amenés à modifier les emplacements spécifiques définis pour un hook d’affichage déterminé, ou encore un module tiers pourrait à son tour souhaiter afficher cet encadré dans un contexte particulier.

Cela serait notamment le cas dans l’utilisation d’un module d’abonnement affichant un ensemble de produits auxquels le client est abonné sur une page qui lui est propre et sur laquelle on souhaiterait afficher les articles de blog qui sont associés à des produits en particulier.

Le concept de widget vise à retirer la limitation à l’utilisation des points d’accroche qui nécessite d’implémenter ces derniers, quitte à...

Modèles

1. Introduction

Au sein du chapitre Au cœur de PrestaShop, une introduction à la classe ObjectModel a été réalisée.

Les spécifications et spécificités relatives à cette classe ne sont pas reprises dans cette section.

Le module conçu durant ce chapitre devant stocker des données relatives à un élément, il est toutefois nécessaire de lui définir un à plusieurs ObjectModel.

2. Définition du modèle

La structure d’une table issue de la base de données définit le modèle.

Les tables dérivées ayant le suffixe _lang et _shop sont des tables issues du même modèle.

Le nom du modèle est libre. On essaie toutefois de le créer de manière évocatrice.

Product est par exemple utilisé pour la table product tandis que nous nommons une catégorie de blog : BlogCategory.

Chaque colonne de la table se représente par une propriété de la classe.

La définition est retranscrite dans la propriété statique du même nom ($definition) sous forme de tableau reprenant le nom de la table, l’identifiant du champ primaire ainsi que les différents champs constituant le modèle. 

<?php 
 
class BlogCategory extends ObjectModel 
{ 
    /** @var int BlogCategory ID */ 
    public $id_blog_category; 
 
    /** @var bool active */ 
    public $active; 
 
    /** @var string title */ 
    public $title; 
 
    /** @var string Object creation date */ 
    public $date_add; 
 
    /** @var string Object last modification date */ 
    public $date_upd; 
 
    /** 
     * @see ObjectModel::$definition 
     */ 
    public static $definition = [ 
        'table' => 'blog_category', 
        'primary' => 'id_blog_category', 
        'multilang_shop' => true, 
        'fields' => [ 
            'active'    => [ 
                'type' => self::TYPE_BOOL, 
                'validate' => 'isBool' 
            ], 
            'date_add'  => [ 
                'type' => self::TYPE_DATE, 
                'validate'...

Contrôleurs

1. Introduction

Les contrôleurs ont la charge de traiter la requête de l’utilisateur afin de faire appel au modèle de données et d’effectuer le rendu des données obtenues mises en forme.

2. Front-office

Un contrôleur front-office permet de présenter les données à l’utilisateur de votre boutique.

Chaque contrôleur est représenté par une classe unique définie dans un fichier devant respecter les règles suivantes :

  • Le fichier est situé dans le dossier controllers/front de votre module.

  • La classe est nommée selon la norme <ModuleClassName><FileName> ModuleFrontController.

  • Elle étend la classe ModuleFrontController.

Sur la base de ces règles, créez le fichier blog.php que vous placez dans le dossier controllers/front et dans lequel vous déclarez la classe correspondante.

<?php 
class EniBlogBlogModuleFrontController extends ModuleFrontController {} 

Votre contrôleur est d’ores et déjà accessible via ce lien : index.php?fc=module&module=eniblog&controller=blog

L’accès à cette URL provoque une erreur concernant la vue.

Afin de définir la vue utilisée par votre contrôleur, vous pouvez définir sa propriété spécifique directement ou bien utiliser une méthode à cet effet.

<?php 
class EniBlogBlogModuleFrontController extends ModuleFrontController 
{ 
    protected $template = 
'module:eniblog/views/templates/front/blog.tpl'; 
 
    public function __construct() 
    { 
        parent::__construct(); 
 
        $this->setTemplate('module:eniblog/views/templates/front/
blog.tpl'); 
    } 
} 

Votre vue est ensuite ajoutée et étend le layout défini pour cette page, communiqué par la variable $layout par PrestaShop.

{* /modules/eniblog/views/templates/front/blog.tpl *} 
{extends file=$layout} 
images/03EI16.png

Au sein d’un contrôleur front-office, vous avez accès à sa propriété $module ayant pour valeur une instance du module associé au contrôleur.

a. Définir une route personnalisée

Lorsque vous souhaitez utiliser une URL personnalisée pour l’accès à votre contrôleur, vous utilisez le point d’accroche moduleRoutes, qui sera traité par le Dispatcher afin de servir votre contrôleur lorsque l’URL appelée par le client correspond à une route précise.

public function hookModuleRoutes($params) 
{ 
    $customRoutes = []; 
 
    $customRoutes['module-' . $this->name . '-blog'] = [ 
        'controller' => 'blog', 
        'rule' => 'blog', 
        'keywords' => [], 
        'params'...

Mises à jour

Lorsqu’une nouvelle version de votre module est installée et que le module requiert des opérations de mise à jour - que cela soit une mise à jour de la base de données ou l’enregistrement d’un nouveau point d’accroche -, celui-ci doit implémenter les actions nécessaires à cette fin.

Dans le contexte où aucune action n’est nécessaire, il n’y a pas lieu de déclarer d’action de mise à jour.

Les mises à jour d’un module ne sont effectuées que lorsqu’un module est effectivement mis à jour d’une ancienne version à une plus récente. Lors d’une installation, ces actions sont ignorées.

Afin de déclarer une action de mise à jour pour, par exemple, la version 1.1.0 de votre module, un fichier nommé upgrade-1.1.0.php est placé dans le répertoire upgrade de votre module.

Dans le nom du fichier, le mot upgrade est libre. Il est cependant conseillé d’utiliser un mot usuel.

PrestaShop se charge de faire appel à la fonction nommée upgrade_module_1_1_0() disponible dans ce fichier. Celle-ci doit retourner un booléen indiquant la réussite ou l’échec de l’application de la mise à jour.

<?php 
 
if (!defined('_PS_VERSION_')) { 
    exit; ...

Traductions

1. Préambule

Les modules disposent de deux systèmes de traduction :

  • Le système legacy utilisant les dictionnaires de fichiers en PHP.

  • Le système moderne basé sur l’utilisation des fichiers XLIFF.

2. Système legacy

Le système legacy, présent depuis la création de PrestaShop se base sur l’utilisation de fichiers PHP dans lesquels sont contenus des tableaux reprenant le message localisé.

Il se présente comme suit :

# translations/fr.php 
 
<?php 
global $_MODULE; 
$_MODULE = []; 
$_MODULE['<{psgdpr}prestashop>psgdpr_5966265f35dd87febf4d59029bc9ef66'] 
= 'RGPD Officiel '; 

L’utilisation de ce système s’effectue par le biais des méthodes l() disponibles dans les différentes classes utiles (Module, ModuleAdminController, ModuleFrontController…) ou encore via l’utilisation de la fonction {l} dans un template Smarty.

// Dans un fichier PHP 
$this->l('Your message'); 
 
// Dans un fichier PHP nommé SpecificFile 
$this->module->l('Your message', 'SpecificFile'); 
 
// Dans un template 
{l s='Your message' mod='enitests'} 

Le deuxième paramètre de la méthode l() permet de contextualiser. Par défaut, le contexte est le nom du module. Par ailleurs il est automatiquement adapté pour un template.

Il n’existe pas de méthode utilitaire pour un template Twig et il n’est pas supporté dans un contrôleur moderne.

Créer le dictionnaire

Pour créer le dictionnaire, autrement dit pour procéder à la traduction du module, cela se passe dans la gestion...

Services

1. Préambule

Le service est un objet PHP, une classe ayant pour objectifs une à plusieurs tâches déterminées.

Aussi bien Symfony que le bundle PrestaShop embarquent différents services.

On retrouve ainsi des services servant à la traduction, à la gestion des configurations ou encore à la création de logs d’erreurs.

La création d’un module permet également l’ajout de services.

2. Ajouter un service

Pour rajouter un service, il faut tout d’abord écrire l’objet PHP servant à le décrire. La classe implémentée n’a pas besoin d’étendre une interface spécifique.

Dans le cadre de ce module de blog, il peut être judicieux d’avoir un service permettant de trouver un ensemble d’articles de blog correspondant à un terme de recherche saisi par l’utilisateur.

Le fichier est placé dans /src/Services/et se nomme ExampleService.php.

Son emplacement n’a pas d’importance. La classe doit juste pouvoir être auto chargée par le biais de Composer.

En voici son ébauche :

<?php 
namespace Eni\Blog\Services; 
 
use Symfony\Component\Translation\TranslatorInterface; 
 
class SearchService { 
    /** @var TranslatorInterface */     private $translator; 
 
    /** 
@param TranslatorInterface $translator 
     */ 
    public function __construct( 
        TranslatorInterface $translator 
    ) { 
        $this->translator = $translator; 
    } 
 
    /** 
@return string 
     */ 
    public function getNoResultsMessage() { 
        return $this->translator->trans('There are no results 
matching your query', [], 'Modules.Eniblog'); 
    } 
} 

Le constructeur hérite d’un argument $translator qui semble implicite. Ceci est vrai grâce à la configuration du service qui est effectuée ci-dessous.

Maintenant que le service est prêt à être utilisé, il est temps d’en déclarer l’existence, au moyen du fichier de configuration prévu à cet effet.

C’est ainsi le fichier /config/services.yml qui sert à rendre le service utilisable dans son applicatif.

services: 
  _defaults: 
    public: true 
    eni.blog.search: ...

Utilisation des grilles

La présentation des données sous forme de liste - que l’on pourrait assimiler au HelperList legacy - se réalise par le biais du composant de grille : Grid.

Au sein du chapitre Au cœur de PrestaShop, une section présentant le composant de grille et son utilisation est réalisée.

L’objectif de cette section est de transposer notre présentation de données utilisée sous la forme d’un HelperList dans notre contrôleur back-office legacy sous sa forme moderne.

1. Définition de la grille

Une grille se compose de plusieurs paramètres, dont l’identifiant et le nom.

Les colonnes, filtres et actions terminent de définir pleinement une grille.

C’est ainsi que la définition d’une grille représentant les catégories de blog peut se retranscrire :

#/src/Grid/Definition/Factory/BlogCategoryGridDefinitionFactory.php 
 
<?php 
namespace Eni\Blog\Grid\Definition\Factory; 
 
use PrestaShop\PrestaShop\Core\Grid\Action\Row\RowActionCollection; 
use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\LinkRowAction; 
use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\SubmitRowAction; 
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection; 
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn; 
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ToggleColumn; 
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn; 
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\
AbstractGridDefinitionFactory; 
 
final class BlogCategoryGridDefinitionFactory extends  
AbstractGridDefinitionFactory 
{ 
    const GRID_ID = 'blog_category'; 
 
    protected function getId() 
    { 
        return self::GRID_ID; 
    } 
 
    protected function getName() 
    { 
        return $this->trans('Categories', [], 'Modules.Eniblog.Admin'); 
    } 
 
    protected function getColumns() 
    { 
        return (new ColumnCollection()) 
            ->add((new DataColumn('id_blog_category')) 
                ->setName($this->trans('ID', [], 'Admin.Global')) 
                ->setOptions([ 
                    'field' => 'id_blog_category', 
                ]) 
            ) 
            ->add((new DataColumn('title')) 
                ->setName($this->trans('Title'...

Utilisation des formulaires

Lors de la conception du contrôleur de configuration, nous avons pu utiliser le composant HelperForm permettant de réaliser des formulaires.

Tout comme le composant Grid est voué à remplacer le composant HelperList, le composant Form est le remplaçant du HelperForm.

Procédons tout d’abord à une adaptation de notre contrôleur de gestion des catégories en lui ajoutant un bouton amenant à la page de création.

/** 
 * @return array[] 
 */ 
private function getToolbarButtons() 
{ 
    return [ 
        'add' => [ 
            'desc' => $this->trans('Add new category', 
'Modules.Eniblog.Admin'), 
            'icon' => 'add_circle_outline', 
            'href' => $this->generateUrl('eniblog_category_create'), 
        ], 
    ]; 
} 
images/03EI32.png

Ajoutons également la route concerné (eniblog_category_create).

eniblog_category_create: 
  path: /new 
  methods: [GET, POST] 
  defaults: 
    _controller: 
'Eni\Blog\Controller\Admin\CategoriesController::createAction' 
    _disable_module_prefix: true 
    _legacy_controller: "AdminEniBlogCategory" 
    _legacy_link: "AdminEniBlogCategory::add" 

1. Conception du formulaire

La composition d’un formulaire repose sur quatre éléments, chacun étant responsable d’opérer sa tâche respective.

On retrouve :

  • le Form Builder pour déclarer le formulaire ;

  • le Form Handler pour traiter la soumission des données ;

  • le Form Data Provider pour transmettre les valeurs de base aux champs affichés ;

  • le Form Data Handler pour enregistrer les données soumises.

Type

La représentation d’un type, servant ainsi à sa définition, est l’ensemble des champs utilisés pour pouvoir donner l’ensemble des informations nécessaires à son enregistrement.

Une date d’anniversaire est constituée d’un jour, un mois et une année. On pourrait définir un type « anniversaire » regroupant deux champs de sélection pour le jour et le mois et un champ texte pour l’année.

PrestaShop propose une longue liste de types, allant du color picker au champ de texte relatif à une adresse IP.

Lorsque votre formulaire concerne un élément bien précis et qu’il vous est possible d’utiliser un type existant, il est vivement suggéré de ne pas créer le vôtre.

Ajoutons toutefois un nouveau type nous permettant d’associer l’ensemble des champs nécessaires à l’enregistrement d’une catégorie pour notre module de blog.

<?php 
 
namespace Eni\Blog\Form; ...

Commandes de console

1. Introduction

Les commandes de console sont des services permettant d’interagir avec votre application en ligne de commande CLI (Command Line Interface).

Dans le chapitre Au cœur de PrestaShop - Console plusieurs commandes issues du bundle PrestaShop ont été évoquées.

Par le biais d’un module, vous êtes en mesure d’ajouter vos propres commandes afin notamment d’effectuer des actions d’export.

2. Définir une commande

La commande est un objet PHP qui doit étendre la classe Symfony\Component\Console\Command\Command.

Votre objet doit par ailleurs implémenter deux méthodes :

  • configure(), servant à définir le nom de la commande.

  • execute(), servant à traiter la commande une fois celle-ci appelée.

Vous pourriez ainsi obtenir une commande d’export des articles de blog suivant la définition suivante.

 <?php 
namespace Eni\Blog\Command; 
 
use Symfony\Component\Console\Command\Command; use  
Symfony\Component\Console\Input\InputInterface; use  
Symfony\Component\Console\Output\OutputInterface; 
 
class ExportCommand extends Command 
{ 
    protected function configure() 
    { 
        $this 
            // Configuration du nom 
            ->setName('eniblog:export') ...

Utilisation du CQRS

Dans le chapitre d’introduction, nous avons introduit l’utilisation du CQRS au sein de PrestaShop.

Avant de poursuivre la lecture de cette partie, nous vous invitons vivement à relire cette introduction si l’architecture ne vous est pas familière.

Dans un module, ce système peut s’utiliser de bien des manières : pour récupérer une série de données, pour effectuer un enregistrement ou une modification de ces données…

1. Création des commandes

Afin de pouvoir utiliser des commandes, il est tout d’abord nécessaire de les implémenter.

Ajoutons en premier lieu une commande pour la création.

<?php 
# /src/Command/AddBlogCategoryCommand.php 
 
namespace Eni\Blog\Command; 
 
/** 
 * 
 */ 
class AddBlogCategoryCommand 
{ 
    /** 
     * @var bool 
     */ 
    private $active; 
 
    /** 
     * @var string[] 
     */ 
    private $title; 
 
    /** 
     * @var string[] 
     */ 
    private $description; 
 
    /** 
     */ 
    public function __construct(bool $active, array $title, 
array $description) 
    { 
        $this->active = $active; 
        $this->title = $title; 
        $this->description = $description; 
    } 
 
    /** 
     * @return bool 
     */ 
    public function getActive() 
    { 
        return $this->active; 
    } 
 
    /** 
     * @return string[] 
     */ 
    public function getTitle() 
    { 
        return $this->title; 
    } 
 
    /** 
     * @return string[] 
     */ 
    public function getDescription() 
    { 
        return $this->description; 
    } 
} 

Procédons ensuite à l’ajout de la commande d’édition, qui est identique à la précédente, à la nuance près qu’elle a une propriété de plus permettant de gérer l’identifiant de l’entité.

<?php 
# /src/Command/EditBlogCategoryCommand.php 
 
namespace Eni\Blog\Command; 
 
/** 
 * 
 */ 
class EditBlogCategoryCommand ...

Cas particulier

1. Module de paiement

Les modes de paiement associés à une boutique le sont obligatoirement par l’utilisation d’un module. Il n’est pas possible d’ajouter de nouveau mode de paiement manuellement.

Un même module peut gérer plusieurs options de paiement.

a. Déclaration d’un module comme module de paiement

Pour que votre module devienne un module de paiement, il doit étendre la classe PaymentModule, qui étend à son tour la classe Module.

<?php 
// PaymentModule étend Module 
class EniPayments extends PaymentModule 
{ 
    public function install() 
    { 
        $hooks = [ 
            'paymentOptions', 
            'displayPaymentReturn', 
        ]; 
 
        return 
            parent::install() 
            && $this->registerHook($hooks); 
    } 
 
} 

La classe PaymentModule embarque un ensemble de propriétés et de méthodes utiles à cet effet.

Les propriétés $currencies et $currencies_mode vous permettent de définir des restrictions sur les modes de paiement en fonction des devises.

Le mode de restriction peut être défini via des cases à cocher (checkbox) ou un sélecteur unique (radio).

Le premier cas permet d’associer plusieurs devises à un mode de paiement tandis que le second cas de figure force cette association à une devise unique.

images/03EI26.png

Ces éléments sont définis sur le module et non sur un mode de paiement.

Les modules de paiement peuvent également être restreints en fonction du groupe de clients, d’un pays ou encore d’un transporteur utilisé pour le panier courant.

b. Ajout des modes de paiement

Les modes de paiement ne sont jamais enregistrés dans la base de données.

L’ajout de mode de paiement se réalise par le biais du point d’accroche paymentOptions

Celui-ci requiert un objet (ou un tableau d’objets) de type \PrestaShop\ PrestaShop\Core\PaymentOption en retour.

Cet objet comporte un ensemble de propriétés accessibles par un getter et un setter. Toutes les propriétés ne sont pas toujours utilisées.

L’ensemble des méthodes utilisées sont chaînables.

Les données $callToActionText et $action doivent obligatoirement être renseignées.

$option = new \PrestaShop\PrestaShop\Core\Payment\PaymentOption(); 
 
$option->setCallToActionText($this->l('Mode de paiement')); 
 
$option->setAction($actionLink); 
); 

Vous pouvez également ajouter un logo à votre mode de paiement.

$option ->setLogo(Media::getMediaPath(_PS_MODULE_DIR_.$this-> 
name.'/payment.jpg')); 

De même, il est possible d’afficher du texte informatif lors du choix...

Cas avancés : utilisation de Vue.js

1. Préambule

Vue.js est un framework JavaScript reposant sur l’utilisation de composants et qui ne requiert pas de configurations serveurs spécifiques, permettant ainsi de l’utiliser dans un module PrestaShop, notamment dans la partie Back End.

Son utilisation n’est pas fort répandue mais, toutefois, de nombreux modules officiels développés par PrestaShop s’appuient dessus.

Il s’agit principalement des modules de la gamme PS Essentials (Checkout, Metrics…) ou encore le module Blockwishlist.

Voici la raison pour laquelle une introduction rapide à son implémentation dans un module est énoncée dans cet ouvrage.

2. Créer son application

La documentation officielle de Vue.js donne plusieurs possibilités concernant son installation, notamment son importation par le biais de la balise <script> de votre document.

Cette implémentation rapide à mettre en œuvre est utile pour des tests rapides. 

Toutefois, nous allons privilégier une méthode d’installation préconisée par PrestaShop lors de développements plus conséquents..

L’installation se fera donc par le biais de NPM, en ligne de commande.

Procédez à l’installation de Vue.js CLI de la sorte :

npm install -g @vue/cli 

Ceci a pour effet d’installer Vue.js CLI, globalement.

Une fois cette installation réalisée, il est désormais possible d’initialiser une application rapidement :

vue create _dev 

Vous pouvez également utiliser la commande vue ui afin de réaliser cette étape via une interface graphique.

Il est possible que Vue.js CLI vous retourne une erreur due à l’utilisation du caractère _ dans le nom de l’application. Dans ce cas, retirez-les. Vous pourrez le rajouter ensuite au dossier créé.

Il vous est demandé de choisir la version de Vue pour votre application.

L’exemple illustré se repose sur Vue 2.

En vous rendant dans le dossier _dev désormais rempli de fichiers constituant votre application, vous pouvez compiler votre application.

npm run build 

L’application construite étant indépendante, vous pourriez ouvrir celle-ci par le biais du script serve.

3. Nettoyer son installation

Avant de poursuivre à proprement parler le développement de son application, il est tout d’abord nécessaire de faire un tri dans certains éléments de celle-ci relatifs à une utilisation indépendante.

Pour cela, supprimez le dossier _dev/public...