Depuis la version 1.7 de Prestashop il est possible de faire des modules qui peuvent s'accrocher à n'importe quel point d'accroche sans devoir toucher au code du module.
C'est très pratique quand il s'agit d'afficher par exemple un petit message à plusieurs endroits d'un site.
On peut donc choisir d'afficher le module en page d'accueil, dans le pied de page, en page produit... N'importe où !
[image page admin positions]
Voyons ci-dessous comment faire un petit module tout simple qui affiche une phrase.

Architecture minimale d'un module Prestashop

Les modules Prestashop sont dans le répertoire "modules" à la racine de la boutique. Pour commencer, on ajoute un répertoire à l'intérieur avec comme nom, le nom de notre nouveau module. On va l'appeler : mysentence

Les fichiers :

index.php : pour empêcher le listing des fichiers du modules.
On trouve un exemple de fichier index.php que l'on peut copier dans n'importe quel répertoire de modules natifs de Prestashop.
On peut donc copier par exemple ps_facetedsearch/index.php dans notre répertoire mysentence/index.php
logo.png
Idem, on peut copier ps_facetedsearch/logo.png dans mysentence/logo.png
mysentence.php : le fichier source principal du module que nous allons voir en détails plus bas
mysentence.tpl (ou autre nom) : le fichier template utilisé par ce module

Le fichier source PHP principal du module

Le code de ce module sera délibérement très épuré et simple. Pas de configuration en back-office du module, pas de superflus ! Le but du module est de pouvoir afficher une phrase sur n'importe quel point d'accroche (hook) disponible.

L'en-tête :

La partie "commentaire : licence, auteur, copyright..." du module. Ce n'est pas "nécessaire" pour le fonctionnement du module, mais obligatoire quand on veut valider son module sur addons. Un exemple de code ci-dessous :


<?php
/**
 * 2007-2018 PrestaShop.
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/AFL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to https://www.prestashop.com for more information.
 *
 * @author    PrestaShop SA <contact@prestashop.com>
 * @copyright 2007-2018 PrestaShop SA
 * @license   https://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */

Ensuite vient le test pour voir si on est bien dans Prestashop et si on a bien sa version en testant la variable globale de Version _PS_VERSION_.


if (!defined('_PS_VERSION_')) {
    exit;
}

La classe du module, son héritage et son interface

On choisit d'utiliser l'interface qui permet de créer un module Widget pour Prestashop. On indique également que le module est une classe héritant de la classe Module et va implémenter cette interface Widget.


use PrestaShop\PrestaShop\Core\Module\WidgetInterface;

class mysentence extends Module implements WidgetInterface
{

Le constructeur du module

Le constructeur d'un module est assez simple. On indique plusieurs informations clefs du module comme :

  • Son nom
  • Sa description
  • Son auteur
  • La version minimale de Prestashop supportée

Ci-dessous le code d'un constructeur tout simple :


   private $templateFile;

    public function __construct()
    {
        $this->name = 'mysentence';
        $this->tab = 'front_office';
        $this->version = '1.0.0';
        $this->author = 'Odatam.com';
        $this->need_instance = 0;

        $this->bootstrap = true;
        parent::__construct();

        $this->displayName = $this->trans('Mysentence', [], 'Modules.Mysentence.Mysentence');
        $this->description = $this->trans('Allows to add a sentence anywhere', [], 'Modules.Mysentence.Mysentence');

        $this->ps_versions_compliancy = array('min' => '1.7.4.0', 'max' => _PS_VERSION_);

        $this->templateFile = 'module:mysentence/mysentence.tpl';

    }

On indique bootstrap = true pour dire à Prestashop si le module est compatible avec Bootstrap.
La propriété need_instance permet de dire si une instance du module doit être chargée dans la page liste des modules. Généralement c'est inutile.
Pour cet exemple de petit module on déclare une propriété "templateFile" qui indique le fichier template utilisé par le module. C'est une propriété qui sera utilisée plus tard dans le module.

Les méthodes install() et uninstall()

Comme leur nom l'indique ces méthodes sont appelées à l'installation du module et à la désinstallation.
On appelle la méthode parente de la classe Module pour chaque méthode afin que Prestashop effectue les traitements courants. On ajoute dans l'exemple ci-dessous l'enregistrement d'un point d'accroche pour notre module sur le Hook displayHome.


    public function install()
    {
        return parent::install()
            && $this->registerHook('displayHome');
    }
    public function uninstall()
    {
        return parent::uninstall();
    }

On ajoute une petite fonction pour indiquer à Prestashop que l'on utilise le nouveau système de traduction disponible depuis la version 1.7.6.0 (Plus d'information ici sur ce nouveau système).


	public function isUsingNewTranslationSystem()
	{
		return true;
	}

Les méthodes pour l'affichage du widget en front-office

Lorsqu'un visiteur charge une page du site, Prestashop appelle la méthode renderWidget du module si celui-ci est accroché à un hook actif dans le thème utilisé. Par exemple dans notre cas, quand on charge la page d'accueil, le hook displayHome est éxécuté et Prestashop va donc lancer la fonction renderWidget de notre module.
Voici notre méthode :

	
    public function renderWidget($hookName = null, array $configuration = [])
    {
        if (!$this->isCached($this->templateFile, $this->getCacheId())) {
		$this->smarty->assign($this->getWidgetVariables($hookName, $configuration));
        }

	return $this->fetch($this->templateFile, $this->getCacheId());
    }
    public function getWidgetVariables($hookName = null, array $configuration = [])
    {
	$sentence = $this->trans('Hello mysentence !', [], 'Modules.Mysentence.Mysentence');
		
        return array(
            'sentence' => $sentence,
        );
    }

On remarque l'utilisation de la méthode $this->isCached qui permet d'utiliser le cache Prestashop si disponible pour stocker le résultat html du template.
C'est très utile voir obligatoire pour ne pas avoir un module qui augmente le temps de chargement des pages.
Grossièrement, on teste si le résultat a déjà été généré pour ce template et si c'est le cas on le charge depuis le cache.
Sinon, on donne au moteur de template Smarty les variables pour générer le résultat de ce template. Pour cela on utilise une méthode toute simple qui va fournir un tableau avec nos variables.
En l'occurence la variable "$sentence" contenant notre phrase à afficher.
On indique en paramètre de la méthode fetch le même "cacheId" utilisé plus haut afin qu'elle puisse l'utiliser. Voilà, c'est tout, la méthode retourne le résultat html compilé ce qui doit ajouter notre phrase dans la page à l'endroit du Hook.

Le code du template smarty du module

J'oubliais le .tpl du module, le template ! Le voici :

<div style="font-size: large; color: #ff0000;">{$sentence nofilter}</div>

Que dire de plus ? C'est très simple on indique juste à notre template d'insérer le résultat de notre variable $sentence sans filtrer le résultat (on peut donc mettre de l'html ou autre dans la variable).

Quel intérêt de faire un Widget ?

L'intérêt c'est pouvoir réutiliser le module sur n'importe quel hook ! Exemple, on accroche notre module sur displayTop grâce au menu "Apparences > Positions" et le bouton "Greffer un module". On recharge notre page d'accueil et là qu'est-ce que l'on voit !?
Notre module s'affiche également en haut du site.
Simple mais efficace, sans aucune retouche dans le code source du module.

On a étudié dans cet article un module très très simple compatible Prestashop 1.7.
Il y a beaucoup de choses à savoir sur les modules, vous trouverez des informations dans la documentation officielle de Prestashop. Consulter le code source des modules natifs aide aussi beaucoup vous pouvez lire les codes sources disponibles sur le compte Github de Prestashop.

Si vous avez besoin d'aide vous pouvez me contacter ici pour vous accompagner dans la création de votre module