Prestashop 1.4 : Marre des Hooks ? Essayez un plugin !

Logo PrestashopAujourd’hui, je vous propose une petite traduction / adaptation d’un article de ecartservice.net qui m’a bien servi.

Si comme moi, vous développez des modules et des themes pour Prestashop, vous vous êtes certainement arraché quelques cheveux lorsque vous avez du vous servir du système de hooks.

Autant cela peut s’avérer très pratique lorsque vous devez coder une fonctionnalité simple (rajouter un évènement après une commande par exemple), autant cela peut devenir très complexe lorsque vous avez une fonctionnalité qui doit s’attacher sur plusieurs hooks ou à des endroits non prévus dans le core de Prestashop.

La version 1.4 de Prestashop a quand même apporté une grande évolution avec son système d’override de classes mais si vous développez des modules, vous ne pourrez pas échapper à l’utilisation de Hooks.

Aujourd’hui, je vous propose de vous affranchir de ceux-ci pour utiliser ce que nous appelerons un Plugin. Son but est de pouvoir afficher n’importe quel affichage de module, page CMS ou variable de config Prestashop, à n’importe quel endroit dans votre theme, et ce sans avoir à vous accrocher à des hooks.

Pour cela, créons une classe Plugin dans le fichier Plugin.php que nous mettrons dans le dossier /overrides/classes/ :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
class Plugin
{
  public static $initialized = false;
  protected static $smarty;
  protected static $cookie;
  protected static $link;
  protected static $cart;
  function init()
  {
    global $smarty, $cookie, $link, $cart;
    if (self::$initialized)
      return;
    self::$initialized = true;
    self::$cookie = $cookie;
    self::$cart = $cart;
    self::$smarty = $smarty;
    self::$link = $link;
    if (!Configuration::get('PS_FORCE_SMARTY_2'))
    {
      self::$smarty->registerPlugin('function', 'plugin', array('Plugin', 'mc_smartyplugin'));
      self::$smarty->registerPlugin('function', 'cmspage', array('Plugin', 'mc_smartycmspage'));
      self::$smarty->registerPlugin('function', 'psconfig', array('Plugin', 'mc_smartypsconfig'));
    } else {
      self::$smarty->register_function('plugin', array('Plugin', 'mc_smartyplugin'));
      self::$smarty->register_function('cmspage', array('Plugin', 'mc_smartycmspage'));
      self::$smarty->register_function('psconfig', array('Plugin', 'mc_smartypsconfig'));
    }
  }
  public static function moduleoutput($module, $hook, $hookArgs = array())
  {
    $output = '';
    if (!isset($hookArgs['cookie']) OR !$hookArgs['cookie'])
      $hookArgs['cookie'] = self::$cookie;
    if (!isset($hookArgs['cart']) OR !$hookArgs['cart'])
      $hookArgs['cart'] = self::$cart;
    $hookArgs['altern'] = 1;
    $instance = Module::getInstanceByName($module);
    if (is_callable(array($instance, 'hook'.$hook)))
      $output = call_user_func(array($instance,'hook'.$hook), $hookArgs);
    echo $output;
  }
  public static function cmspage($id_cms = 1)
  {
    $output = '';
    $cms = new CMS($id_cms, intval(self::$cookie->id_lang));
    if (Validate::isLoadedObject($cms))
      $output = $cms->content;
    return $output;
  }
  static function mc_smartyplugin($params, &$smarty)
  {
    return Plugin::moduleoutput($params['module'], $params['hook'], isset($params['args']) ? $params['args'] : array());
  }
  static function mc_smartycmspage($params, &$smarty)
  {
    return Plugin::cmspage($params['id']);
  }
  static function mc_smartypsconfig($params, &$smarty)
  {
    return Configuration::get($params['item']);
  }
}

Maintenant, faisons en sorte que Prestashop prenne en compte notre nouvelle classe dès l’initialisation du programme (fonction init du FrontController). Pour cela, nous allons surcharger le controller principal afin d’initialiser notre classe Plugin.

Créez le fichier FrontController.php dans /overrides/classes/ avec le contenu suivant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
class FrontController extends FrontControllerCore
{
  protected static $plugin;
  function __construct()
  {
    parent::__construct();
    self::$plugin = new Plugin();
  }
  function init()
  {
    parent::init();
    self::$plugin->init();
  }
}

Voilà notre classe Plugin est utilisable à présent.

Pour la mettre en oeuvre, rien de plus simple, vous pouvez utiliser les 3 syntaxes suivantes :

  1. {plugin module='nomdevotremodule' hook='home'}

    ce qui affichera la « sortie » de votre module se nommant « nomdevotremodule« 

  2. {cmspage id='2'}

    ce qui affichera le contenu de la page CMS ayant l’identifiant 2. Très pratique par exemple pour rajouter du contenu dans une page comme la page contact.php qui n’a rien de prévu à cet effet de base dans Prestashop

  3. et enfin :
    {psconfig item='PS_SHOP_PHONE'}

    qui vous permettra d’insérer où vous voulez le contenu des variables de configuration de Prestashop comme ici le numéro de téléphone de votre magasin

Note importante: attention, même si ce code a bien été testé, si vous l’utilisez, je ne garantis pas le bon fonctionnement de votre boutique Prestashop

Vous pouvez répondre, ou faire un trackback depuis votre propre site web.

13 Réponses sur “Prestashop 1.4 : Marre des Hooks ? Essayez un plugin !”

  1. capsizone dit :

    Bonjour,

    Et merci. Très intéressant en effet de pouvoir se libérer de cette contrainte des hooks. Je viens de tester, malheureusement ça ne fonctionne pas pour moi (V1.4.4.1); j’obtiens ceci:
    class FrontController extends FrontControllerCore { protected static $plugin; function __construct() { parent::__construct(); self::$plugin = new Plugin(); } function init() { parent::init(); self::$plugin->init(); } }
    Je ne suis qu’un modeste intégrateur et je ne sais pas interpréter ce bout de code.

    • admin dit :

      Bonjour,

      je ne comprends pas bien ton souci, le bout de code que tu donnes est celui de la classe FrontController qui surcharge la classe existante du core de Prestashop …
      Tu as un message d’erreur particulier ?

      • capsizone dit :

        C’est ce qui apparait sur une page blanche quand j’accède au front office après avoir mis les deux fichiers dans /override/classes/.

        • admin dit :

          C’est tout simplement qu’il faut rajouter le tag d’ouverture < ?php en haut du fichier FrontController.php que j'ai oublié d'insérer dans mon code ...
          Je le rajoute dans l'article.
          Ca devrait fonctionner à présent !

          • capsizone dit :

            Super, merci; quand je disais que j’étais limité au niveau développement…
            Je viens de faire quelques tests et apparemment pas de soucis. Plus qu’à modifier le css. Je vais penser différemment maintenant quand je commencerais un nouveau thème. Je peux mettre un lien vers ton article ?

          • admin dit :

            De rien !
            Et oui tu peux mettre un lien sans problème ;)

  2. Philippe dit :

    Bonjour,

    C’est très intéressant, mais je suis un peu perdu pour la mise en oeuvre.

    Je ne vois pas dans quel fichier dans il faut placer les instructions (les 3 syntaxes).

    Merci par avance.

    Philippe

    • Michel dit :

      Bonjour,

      il faut tout simplement mettre le code dans un fichier tpl à l’endroit où tu veux afficher le contenu de ta page cms.
      Exemple si tu veux rajouter du contenu sur la page contact juste au dessus du formulaire (cette page utilise le fichier contact-form.tpl), tu inseres le code ici (ligne 12 de mon exemple) : Attention je n’ai pas repris le code intégral du tpl ;)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      {if isset($confirmation)}
      	{l s='Your message has been successfully sent to our team.'}
       
      		<a href="{$base_dir}" rel="nofollow"></a><a href="{$base_dir}" rel="nofollow">{l s='Home'}</a>
       
      {elseif isset($alreadySent)}
      	{l s='Your message has already been sent.'}
       
      		<a href="{$base_dir}" rel="nofollow"></a><a href="{$base_dir}" rel="nofollow">{l s='Home'}</a>
       
      {else}
      {cmspage id='8'}
      	{l s='For questions about an order or for more information about our products'}.
      	{include file="$tpl_dir./errors.tpl"}

      Cordialement

      • Philippe dit :

        Bonjour,

        Merci, ça fonctionne excepté l’appel d’un module avec la syntaxe: »{plugin module=’nomdevotremodule’ hook=’home’} »

        J’ai essayé d’avoir le module « blockcart » ou « blockcms » sur plusieurs tpl, sans succès.

        Je pense faire une erreur quelque part, mais où ??

        Tu pourrais me dire où est le problème?

        Merci encore

        Cordialement

        Philippe

        • Michel dit :

          Bonsoir,

          pour savoir d’où vient le problème, il me faudrait tout d’abord plus d’éléments …
          Y a t’il un message d’erreur affiché ? Est ce une page blanche qui s’affiche ?
          Copie moi tes erreurs s’il y en a que je t’aide à debugger le script.

          Merci !
          Michel

  3. RegisD dit :

    wow, je viens juste de tomber sur ton article, habitué au dev sur WordPress et son système de template/plugin en php, je suis justement en train de me battre avec les usages des presta que je trouves parfois assez bizarres (me retrouver obligé de mettre mes éléments propres au thème sous forme de module en dehors du dossier du thème par ex), la limite des hooks imposés (être obligé de modifier la bdd pour pouvoir en ajouter…wtf! )… smarty… Je vais me dépêcher de tester ce hack, ça m’a l’air bien pratique pour mettre en place des thèmes sortant un peu des sentiers battu imposés implicitement par Presta, ou juste avoir un code un peu plus clair, en voyant directement dans le code quel module va où), bref merci.

    • olivier dit :

      Je suis d’accord c’est vraiment galère quand on viens de wordpress.
      Les hooks rajoute un boulo monstre.
      Il ferait mieux d’utilisez un système de widget Optionnel.

      Bref quelque sait comment créer une scène sur la page d’accueil?

  4. M'sieur Toph' dit :

    Yeeees!

    Ce ‘plugin’ est génial!
    C’est exactement ce que je cherchais. Les hook sont un vrai supplice (dans la manière dont prestashop les utilise … parce que dans l’idée, c’est plutôt une bonne intention), ça oblige à surcharger la couche métier, alors que c’est la couche graphique que l’on veut modifier. Bref .. une galère quoi!

    Grâce à ta classe, je suis libéré de ça … vraiment, c’est une tuerie! Tout simple, mais tellement bien pensé!

    Merci à toi pour le fruit de ton travail!

Donner votre avis