Développer un module PrestaShop 1.627Avr.2018

Tutoriel : Créer un module PrestaShop 1.6

Comme vous le savez sûrement, Ukoo réalise de belles boutiques e-commerces sous PrestaShop ! Nous ajoutons et concevons des fonctionnalités utiles pour le quotidien des e-commerçants.
Mais comme nous ne pouvons pas être partout, nous allons voir ensemble comment créer votre propre module.

Cette intro vous dis quelque chose ? C’est normal, ce tutoriel a déjà été présenté il y a 6 ans.
Mais de nombreuses choses ont évoluées. Parmi elles les versions de PrestaShop : c’est pour cela que nous avons remis à jour notre module et son tutoriel sur la version 1.6 de PrestaShop.

Let’s do this !

Commençons par le commencement

Pour bien débuter, nous devons définir le besoin auquel répondra notre module. Pour ma part, le module permettra d’afficher 3 témoignages, sur la colonne de gauche ou de droite, avec un petit défilement que nous réaliserons via JavaScript.

Ça reste assez sommaire, mais le but est de vous fournir un module fonctionnellement identique à son prédécesseur, afin que vous puissiez comparer les évolutions induites par PS1.6.

structure d’un module PrestaShop 1.6

Tout d’abord, le plus important pour un module, c’est d’avoir une arborescence de fichiers que PrestaShop pourra comprendre et où n’importe quel autre développeur pourra se retrouver (c’est la magie de l’Open Source). Vous pouvez regarder d’autres modules déjà présent dans votre site (de préférences les modules natifs ou de développeurs de confiances et reconnus [comme nous ^^]) et vous pourrez voir que la structure sera généralement la même.

Voici la structure que nous retiendrons donc :

/testimony (dossier du module)

  • /translations (dossier contenant les fichiers de traduction du module)
  • /views
    • /css
      • index.html
      • testimony.css
    • /js
      • index.html
      • testimony.js
    • /templates
      • /hook
        • index.php
        • testimony.tpl
      • index.php
    • index.php
  • index.php
  • testimony.php
  • logo.png

Code PHP d’un module PrestaShop 1.6 !

Index.php

Comme vous pouvez le voir, chaque dossier contient un fichier index.php. Ce fichier sert à restreindre l’accès direct à votre module, et à rediriger le petit malin vers la page d’accueil de votre boutique.

Le fichier index.php peut-être rapidement rempli grâce au code que je vous fournis.

header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified:'.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

Le coeur du module

Pour continuer, nous attaquons le fichier coeur du module : testimony.php

Ce fichier contient le plus important : l’installation, la désinstallation et la configuration, mais aussi toutes les fonctions personnalisées que vous souhaitez y ajouter.

En premier lieu, le morceau de code suivant est le strict minimum pour avoir un module installable :

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

class Testimony extends Module
{
   public function __construct()
   {
       $this->name = 'testimony';
       $this->tab = 'front_office_features';
       $this->version = '2.0.0';
       $this->author = 'Ukoo';
       $this->need_instance = 0;
       $this->context = Context::getContext();
       $this->bootstrap = true;
       parent::__construct();
       $this->displayName = $this->l('Testimony');
       $this->description = $this->l('Display a block with customer testimonials');
       $this->confirmUninstall = $this->l('Are you sure you want to uninstall this module ?');
   }
}

Nous créons une nouvelle classe qui étend la classe Module déjà existante dans PrestaShop.

La fonction __construct (constructeur) permet de créer une instance de cette classe.

Le module peut déjà être installé comme tous les modules depuis l’administration de PrestaShop (onglet « Modules et services »).

Variables de configuration

Le but étant de stocker 3 témoignages dans la base de données, nous allons utiliser la table ps_configuration de PrestaShop.

Dans la classe Testimony, nous devons rajouter la fonction suivante :

public function install()
{
   if (Shop::isFeatureActive()) {
       return Shop::setContext(Shop::CONTEXT_ALL);
   }
   return parent::install() &&
       $this->registerHook('displayLeftColumn') &&
       $this->registerHook('displayRightColumn') &&
       $this->registerHook('header') &&
       Configuration::updateValue('TESTIMONY1', '') &&
       Configuration::updateValue('TESTIMONY2', '') &&
       Configuration::updateValue('TESTIMONY3', '');
}

Lors de l’installation du module, cette fonction sera exécutée par PrestaShop.

Après avoir effectuer le processus d’installation « standard » des modules, PrestaShop va greffer notre module à différents hooks : la colonne de gauche, de droite et le header pour le CSS et le JavaScript. Puis il créera les variables de configuration qui nous serviront à stocker nos données.

Bien-sûr, qui dit : “installation”, dit : “désinstallation”. Lors de celle-ci; nous devons donc prévoir la suppression de ces variables de la base de données grâce à la fonction suivante.

public function uninstall()
{
   return parent::uninstall() &&
       Configuration::deleteByName('TESTIMONY1') &&
       Configuration::deleteByName('TESTIMONY2') &&
       Configuration::deleteByName('TESTIMONY3');
}

Ajouter un lien vers la configuration du module

Le lien vers la configuration du module est créé automatiquement si vous rajoutez la fonction suivante dans votre classe :

public function getContent()
{
   $output = null;
   if (Tools::isSubmit('submit' . $this->name)) {
       $testimony1 = Tools::getValue('TESTIMONY1');
       $testimony2 = Tools::getValue('TESTIMONY2');
       $testimony3 = Tools::getValue('TESTIMONY3');
       if (!$testimony1 || empty($testimony1) || !Validate::isGenericName($testimony1)) {
           $output .= $this->displayError($this->l('Configuration failed'));
       } else {
           Configuration::updateValue('TESTIMONY1', $testimony1);
           Configuration::updateValue('TESTIMONY2', $testimony2);
           Configuration::updateValue('TESTIMONY3', $testimony3);
           $output .= $this->displayConfirmation($this->l('Update successful'));
       }
   }
   return $output . $this->displayForm();
}

Comme nous pouvons voir à la fin de cette fonction, une autre fonction « displayForm() » est appelée. Elle permet de générer le formulaire.

Créons tout d’abord les champs de ce formulaire. Pour cela, nous devons définir le tableau $fields_form qui sera transmis ensuite au HelperForm de PrestaShop :

public function displayForm()
{
   $fields_form = array();
   $default_lang = (int)Configuration::get('PS_LANG_DEFAULT');
   $fields_form[0]['form'] = array(
       'legend' => array(
           'title' => $this->l('Testimonies settings'),
       ),
       'input' => array(
           array(
               'type' => 'textarea',
               'label' => $this->l('Testimony 1'),
               'name' => 'TESTIMONY1',
               'size' => 20,
               'required' => true
           ),
           array(
               'type' => 'textarea',
               'label' => $this->l('Testimony 2'),
               'name' => 'TESTIMONY2',
               'size' => 20,
               'required' => false
           ),
           array(
               'type' => 'textarea',
               'label' => $this->l('Testimony 3'),
               'name' => 'TESTIMONY3',
               'size' => 20,
               'required' => false
           )
       ),
       'submit' => array(
           'title' => $this->l('Save'),
           'class' => 'btn btn-default'
       )
   );
}

On instancie ensuite, au sein de la fonction précédente, un objet HelperForm afin de définir notre formulaire.

$helper = new HelperForm();
$helper->module = $this;
$helper->name_controller = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
$helper->default_form_language = $default_lang;
$helper->allow_employee_form_lang = $default_lang;
$helper->title = $this->displayName;
$helper->show_toolbar = true;
$helper->toolbar_scroll = true;
$helper->submit_action = 'submit' . $this->name;
$helper->toolbar_btn = array(
   'save' =>
       array(
           'desc' => $this->l('Save'),
           'href' => AdminController::$currentIndex . '&configure=' . $this->name . '&save' . $this->name .
               '&token=' . Tools::getAdminTokenLite('AdminModules'),
       ),
   'back' => array(
       'href' => AdminController::$currentIndex . '&token=' . Tools::getAdminTokenLite('AdminModules'),
       'desc' => $this->l('Back to list')
   )
);

Toujours dans cette même fonction, nous devons également définir la valeur que prendrons nos champs si leur contenu est déjà défini. Ceci aura pour effet de pré-remplir nos champs de témoignages avec les valeurs précédemment saisies.

$helper->tpl_vars = array(
   'fields_value' => array(
       'TESTIMONY1' => Configuration::get('TESTIMONY1'),
       'TESTIMONY2' => Configuration::get('TESTIMONY2'),
       'TESTIMONY3' => Configuration::get('TESTIMONY3')
   ),
);

Et pour finir, il ne nous reste qu’à générer le formulaire grâce à une fonction déjà présente dans PrestaShop (toujours à rajouter au sein de la fonction précédente) :

return $helper->generateForm($fields_form);

Tests de mi-parcours

A ce niveau de votre avancement vous devriez avoir un module installable, désinstallable et configurable.

Les variables de configuration TESTIMONY1, 2 et 3 devraient être créées (vides) en base de données, dans la table ps_configuration.

Vous devriez pouvoir accéder à la configuration de votre module à travers l’interface de PrestaShop, et l’enregistrement du formulaire devrait enregistrer vos témoignages en base de données.

La désinstallation de votre module devrait également supprimer toute trace du module en base de données.

affichage front-office d’un module PrestaShop 1.6 !

Quand la configuration est terminé, vous voulez sûrement voir apparaître vos témoignages en front-office !

Nous devons greffer notre module à des hooks :

public function hookheader()
{
   $this->context->controller->addJS($this->_path . '/views/js/testimony.js', 'all');
   $this->context->controller->addCSS($this->_path . '/views/css/testimony.css', 'all');
}

En déclarant cette méthode, PrestaShop comprend que notre module peut être greffé au hook « header » de la boutique. Il s’agit ici simplement d’appliquer un fichier CSS et JS à notre module dans le header des pages du front-office.

public function hookDisplayLeftColumn($params)
{
   $this->context->smarty->assign(
       array(
           'testimony1' => Configuration::get('TESTIMONY1'),
           'testimony2' => Configuration::get('TESTIMONY2'),
           'testimony3' => Configuration::get('TESTIMONY3'),
       )
   );
   return $this->display(__FILE__, 'views/templates/hook/testimony.tpl');
}

La déclaration de cette seconde méthode autorise notre module à se greffer dans la colonne de gauche. Vous préférez l’afficher dans la colonne de droite ? Pas de problèmes, ajoutons alors la méthode suivante :

public function hookDisplayRightColumn($params)
{
   return $this->hookDisplayLeftColumn($params);
}

Avec ça, nous arrivons au bout de notre code PHP.

Créons à présent le contenu du fichier /modules/testimony/views/templates/hook/testimony.tpl afin de définir le template (la mise en page) de notre module en front-office.

<div class="block testimonies">
   <h4>{l s='Customers testimonials' mod='testimony'}</h4>
   <div class="block_content">
       <p class="testimony">{$testimony1|escape:'htmlall':'UTF-8'}</p>
       <p class="testimony">{$testimony2|escape:'htmlall':'UTF-8'}</p>
       <p class="testimony">{$testimony3|escape:'htmlall':'UTF-8'}</p>
   </div>
</div>

Afficher simplement nos témoignages, c’est bien, mais qu’ils soit plus attractifs, c’est mieux ! Ajoutons donc un peu de JavaScript afin de créer un joli défilement dynamique (/modules/testimony/views/js/testimony.js).

$(document).ready(function () {
   $(".testimonies .block_content p:not(:first)").each(function () {
       $(this).hide(); // cache les témoignages
   });
   $(".testimonies .block_content p:first").addClass("current");
   setTimeout("slide()", 3000);
});

function slide() {
   var prev = $(".testimonies .block_content p.current");
   if ($(".testimonies .block_content p.current").next().size() > 0) {
       var next = $(".testimonies .block_content p.current").next();
   } else {
       var next = $(".testimonies .block_content p:first");
   }
   prev.removeClass("current");
   next.addClass("current");
   prev.fadeOut();
   next.fadeIn();
   setTimeout("slide()", 3000);
}

Et ajoutons un soupçon de CSS afin de corriger la marge de nos blocs :

div.testimonies .block_content{ position:relative; padding:10px;}

Dernier petit détail : traduire votre module dans d’autres langues.

Pour ce faire, passez par la configuration du module, et cliquez sur le drapeau de la langue dans laquelle vous souhaitez traduire votre module. Je ne me suis occupé que de l’anglais et du français.

Pour aller plus loin !

Voilà, vous êtes venu à bout de ce module. Si vous avez compris ce que vous avez fait c’est déjà un grand pas en avant !

On peut imaginer de multiples améliorations pour ce module :

  • Création d’un nombre illimité de témoignages
  • Configuration du temps de défilement JS
  • etc.

Je vous laisse découvrir toutes les possibilités que vous ouvre cette nouvelle compétence que vous venez d’acquérir. Et n’hésitez pas à en faire profiter la communauté en nous partageant vos modules développés sur base de ce tutoriel…

Télécharger le module du tutoriel

Co-rédigé et développé par Damien Tabet
Stagiaire en développement

Laisser un commentaire

*