Jump to content

Création de module, Hook, override


Recommended Posts

Bonjour à tous,

Je me permets de publier un petit problème que je rencontre lors du développement d'un module très spécifique.

Lors de la création de ce module j'ai impérativement besoin de me greffer a un Hook category qui n'existe évidemment pas.

La solution évidemment est de surcharger le controller Category pour faire appel à ce HOOK. Le problème est que si le controller Category est déjà overridé on rentre dans un système de comparaison de code à n'en plus finir pour savoir ou ajouter la bonne ligne.

Je parle ici de category mais le problème serait le même pour tout autre classes et ou controller.

Alors la question que je me pose aujourd'hui, c'est pourquoi l'équipe Prestashop n'a pas pensé à cette problématique qui va devenir plus que courante dans les prochaines versions de modules.

L'idée étant toujours de faire des modules autonomes.

Ma question est donc la suivante pourquoi ne pas avoir fait dans chacun des controller un système de HOOK_BEFORE_PROCESS et de HOOK_AFTER_PROCESS ?

On aurait ainsi un HOOK_BEFORE_CATEGORY et un HOOK_AFTER_CATEGORY.
Ces appels au Hook seraient faits dans la méthode process() de chaque controller.

Dans ce cas la vie des développeurs est largement simplifiée, je me greffe à tel hook de tel controller et le tour est joué, on a plus qu'à régler les positions.

Je fais peut être fausse route est il est évident que l'on ne peut pas penser à tout. Vu le boulot abattu je dis quand même un grand bravo à la team.

Est ce que cette solution sera envisagée dans une prochaine version ?

@ très vite.
Toutes remarques est la bien venue.

Link to comment
Share on other sites

+1

L'override est super quand on est seul à vouloir surcharger le comportement du core.

Mais absolument pas pratique (voir déconseillé) depuis un module, car effectivement, si plusieurs modules surchargent les mêmes classes du core, ça crée des conflits qu'il faut gérer.

Le souci se pose pour les controlleurs, mais aussi pour toutes les autres classes du core.

Sans compter ceux qui vont surcharger plutôt que de dériver : exemple, rajouter des champs à un objet du core, qui ne sont exploitable que depuis le module qui les crée => il faut bien dériver en non surcharger

Link to comment
Share on other sites

Alors j'ai trouvé une solution et maintenant je souhaiterais savoir si il est possible d'implémenter cette solution en natif dans Prestashop.

A vous de voir la team et il s'agit peut-être juste d'une piste.

Voici ce que j'ai fait.

Dans la classe FrontController
j'ai ajouter un :

public $page_name;



Dans la méthode init() j'ai ajouté :

$this->page_name = strtoupper((preg_match('/^[0-9]/', $page_name)) ? 'page_'.$page_name : $page_name);



Ensuite dans le méthode run après

$this->process();

, j'ai ajouté

$this->postProcess();

.

J'ai ensuite créé la méthode :

public function postProcess()
   {
       self::$smarty->assign(array('HOOK_POST_'.$this->page_name => Module::hookExec('post'.ucfirst(strtolower($this->page_name)))));
   }



Maintenant j'ai créé mon module et à l’installe de celui-ci j'appelle une méthode _setupHook() que voici :

private function _setupHook($uninstall = false) {
       if ($uninstall === false) {
         // We verify if hook exists in database
         $result = Db::getInstance()->getRow('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \'postCategory\'');
         if(!$result)
             DB::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook`
           SET `name`= \'postCategory\',
               `title`= \'After process Category \',
               `description`= \'After process Category\'
          ');
         $this->registerHook('postCategory');
       }
       return true;
     }



Dans mon exemple je prends category mais je pourrais très bien prendre product, cart, adress etc....

Ensuite dans mon module je fais la méthode habituelle :

public function hookPostCategory($params){} 



Et le tour est joué.

Je peux faire pareil pour les pre process.

Avec cette petite pratique je peux faire en sorte que n'importe quel module ce plug en amont ou en aval du process.
Ca permet simplement de gérer une notion d'"observer" que l'on retrouve chez le concurrent "Magento" et je trouve ça très pratique pour le coup.

Et pour le coup vu que je ne suis pas fan du tout du concurrent, j'essaye de faire avancer Presta au max.

Alors la team qu'en pensez-vous ?
Et vous amis développeurs ?

ToM

Link to comment
Share on other sites

Je trouve cette idée géniale.
L'idée des hooks systématiques sur pré et post process des controlleurs est en effet un pouvoir de plus sur la bestiole ...

Bravo, j'espère que ta suggestion aura toute l'attention de la team.

Maintenant je dis ça à la volée et je n'ai absolument pas réfléchi aux éventuels effets de bord.
Le code "d'auto hook" dans FrontController reste à éprouver , tester , tant fonctionnellement que sur le point sécurité.

Link to comment
Share on other sites

Ha là vous me faites plaisirs les amis :)

J'ai soulevé un point que certains d'entres vous ont dû soulever et franchement cette façon de faire est très pratique.

Pour ce qui est des tests fonctionnels je suis en plein dedans et pour le coup et ça roule tout seul. Maintenant pour ce qui est de la sécurité il n'y a pas de raison que cela ait un impact c'est à chaque développeur de modules de faire du code propre. Le système de HOOK reste le même dans le fond.

Le top serait vraiment que tout ces HOOK soient créés à l'instal., ça éviterait d'avoir à faire la vérifications dans l'instal. des modules.

;)

Link to comment
Share on other sites

  • 4 months later...

Alors j'ai trouvé une solution et maintenant je souhaiterais savoir si il est possible d'implémenter cette solution en natif dans Prestashop.<br/><br/>A vous de voir la team et il s'agit peut-être juste d'une piste.<br/><br/>Voici ce que j'ai fait.<br/><br/>Dans la classe FrontController<br/>j'ai ajouter un :<br/>

public $page_name;

<br/><br/>Dans la méthode init() j'ai ajouté :<br/>

$this->page_name = strtoupper((preg_match('/^[0-9]/', $page_name)) ? 'page_'.$page_name : $page_name);

<br/><br/>Ensuite dans le méthode run après

$this->process();

, j'ai ajouté

$this->postProcess();

.<br/><br/>J'ai ensuite créé la méthode :<br/>

public function postProcess()<br/>    {<br/>        self::$smarty->assign(array('HOOK_POST_'.$this->page_name => Module::hookExec('post'.ucfirst(strtolower($this->page_name)))));<br/>    }

<br/><br/>Maintenant j'ai créé mon module et à l’installe de celui-ci j'appelle une méthode _setupHook() que voici :<br/>

<br/>private function _setupHook($uninstall = false) {<br/>        if ($uninstall === false) {<br/>          // We verify if hook exists in database<br/>          $result = Db::getInstance()->getRow('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = 'postCategory'');<br/>          if(!$result)<br/>              DB::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook`<br/>            SET `name`= 'postCategory',<br/>                `title`= 'After process Category ',<br/>                `description`= 'After process Category'<br/>           ');<br/>          $this->registerHook('postCategory');<br/>        }<br/>        return true;<br/>      }<br/>

<br/><br/>Dans mon exemple je prends category mais je pourrais très bien prendre product, cart, adress etc....<br/><br/>Ensuite dans mon module je fais la méthode habituelle :<br/>

public function hookPostCategory($params){} 

<br/><br/>Et le tour est joué.<br/><br/>Je peux faire pareil pour les pre process.<br/><br/>Avec cette petite pratique je peux faire en sorte que n'importe quel module ce plug en amont ou en aval du process.<br/>Ca permet simplement de gérer une notion d'"observer" que l'on retrouve chez le concurrent "Magento" et je trouve ça très pratique pour le coup.<br/><br/>Et pour le coup vu que je ne suis pas fan du tout du concurrent, j'essaye de faire avancer Presta au max.<br/><br/>Alors la team qu'en pensez-vous ?<br/>Et vous amis développeurs ?<br/><br/>ToM

 

Je pense que dans la fonction annoncée, il doit y avoir un problème, je la verrais davantage comme cela :

private function _setupHook($uninstall = false)
{
       if ($uninstall === false) {
         // We verify if hook exists in database
         $result = Db::getInstance()->getRow('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = "postCategory"');
         if(!$result)
             DB::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook`
           SET `name`= "postCategory",
               `title`= "After process Category",
               `description`= "After process Category"
          ');
         $this->registerHook('postCategory');
       }
       return true;
   }	

Link to comment
Share on other sites

Je pense que dans la fonction annoncée, il doit y avoir un problème, je la verrais davantage comme cela :

 

 

Salut,

plutôt comme quoi en fait,parce que la on a juste un copier coller de la fonction initiale ? un oubli ? ;)

 

Il a fait une modif de simple quotes à double quotes car ça collait pas avec la requête SQL ;-)

 

Très intéressant ce post, je vais le réutiliser, l'arrivée en natif serait un vrai plus!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...