Exploiter à 100% le MVC de PrestaShop 1.5

Dans cet article, nous allons voir comment exploiter à fond les trois composantes du design pattern MVC, ainsi que l’utilisation de quelques unes des nombreuses nouveautés de Prestashop 1.5 pour :

  • Créer un modèle objet, qui sera stocké dans la base de données
  • Gérer les vues entièrement en Smarty. Bye bye le code HTML dans le code PHP.
  • Utiliser les Controllers aussi bien pour gérer les page de back office et de front office.

Spécifications

Le module Prestashop que nous allons créer permet aux utilisateurs de donner leur avis sur le site, au travers d’un formulaire sur une page dédiée du front office. Les utilisateurs peuvent choisir dans une liste de valeurs, qui sera stockée en base de données. Dans le back office, un onglet permet de valider les avis des clients, afin de les laisser apparaître sur la page du front office.

Structure du module

La structure des modules sous PrestaShop 1.5 impose une structure plus stricte.

Module MVC Prestashop 1.5

  • /controllers accueille les Controllers de back office et de front office
  • /views accueille les vues Smarty pour les Controllers ainsi que les hooks
  • /models n’est pas obligatoire, mais nous allons y placer les modèles objet

La classe du module

Pour commencer, nous allons créer la classe du module de manière classique.

On greffe le module sur le hook leftColumn lors de l’installation, afin de créer un lien vers la page front office du module.
On note au passage le changement de convention de nommage des hooks : les hooks d’affichage (ceux qui sont visibles), sont désormais préfixés par hookDisplay, tandis que les hooks d’action sont préfixés par hookAction.

Création de la vue pour le hook

Les vues pour les hooks sont désormais à placer dans le dossier /views/templates/hook.
On créé donc le fichier left-column.tpl

On appelle la méthode getModuleLink de la classe Link afin de générer un lien vers la page du module.

Les liens seront de la forme :

URLs classique

http://www.monsite.com/index.php?fc=module&module=prcustomeropinion&controller=default

URL SEO

http://www.monsite.com/module/prcustomeropinion/default

Module MVC Prestashop 1.5


Le Modèle

Nous allons gérer le stockage des avis via la table ci-dessous. On stocke une référénce vers le client qui a donné son avis via la colonne id_customer.

Dans le dossiers /models, on crée un fichier Opinion.php, pour définir le modèle objet :

Comme précédemment, la classe doit étendre ObjectModel afin de pouvoir disposer des fonctionnalités ORM et CRUD, et exposer des propriétés publiques pour les champs de la table.
La nouveauté est l’utilisation du tableau statique $definition pour spécifier les caractéristiques de la table. Ici, on spécifie simplement les champs obligatoires de l’objet.

On ajoute également une méthode permettant de charger tous les avis utilisateurs validés pour l’affichage :

On note l’utilisation de la méthode ObjectModel :: hydrateCollection, qui permet de transformer un tableau de résultats MySQL en instances de classe.


Création du Controller de front office

Affichage de la liste des avis

Dans le dossier /controllers/front, nous ajoutons un fichier default.php, qui va contenir la classe du Controller.

On récupère le tableau d’objets de type Opinion, et on l’assigne à la vue form.tpl, à placer dans le dossier /views/templates/front :

Formulaire client

On va maintenant créer un formulaire qui permet aux client de donner leur avis, autrement dit d’ajouter un enregistrement en base de données.

Dans le Controller, on ajoute le traitement du formulaire (la vérification de l’existence du client a été omise pour l’exemple) :

On se sert simplement des méthodes CRUD de la classe ObjectModel pour stocker l’objet en base.
Lorsque le formulaire est posté, un enregistrement est ajouté dans la table.

La page du module s’affiche bien dans la colonne centrale du thème.

Module MVC Prestashop 1.5


Création du Controller de back office

Nous allons désormais ajouter un onglet dans le back office permettant de valider les avis client, afin que ceux-ci apparaissent sur le front office.

Nous souhaitons donc afficher une liste d’avis, avec des boutons permettant de valider un avis ou de le supprimer.

La classe du Controller

Dans /controllers/admin, on créé un fichier adminopinion.php, qui contrôle le modèle Opinion. Les Controllers de back office sont en effet prévus par défaut pour gérer un modèle objet. Il est cependant possible de faire ce que l’on veut.

Attention, les conventions de nommage sont importantes pour garantir le fonctionnement du Controller.

On ajoute ensuite l’onglet :

Module MVC Prestashop 1.5

Affichage de la liste d’avis à valider

Afin de simplifier et homogéniser l’affichage du back office, PrestaShop 1.5 fournit des View Helpers (Aides de vue) : ce sont en quelques mots des classes qui génèrent du code HTML.

Pour afficher de manière simple la liste des avis, il suffit de specifier des propriétés dans le constructeur du module, par exemple :

La propriété $fields_list permet de personnaliser l’affichage des colonnes de la liste.

Dans l’exemple ci-dessus, la colonne active affichera le bouton standard rouge/vert, et mettra à jour le statut de l’objet en base de données.

Afin de personnaliser la colonne id_customer et afficher le nom complet du client (au lieu de son identifiant), on utilise une fonction de callback. C’est à dire que pour chaque élément de la liste, PrestaShop va appeler une méthode, qui doit retourner la valeur à afficher. Par défaut, la méthode est appelée sur le Controller

Nous ajoutons également le bouton permettant de supprimer un élément de la liste via la variable $actions

Et… C’est tout !

En effet, dans ce cas il est inutile de créer une quelconque vue, car l’affichage est intégralement pris en charger par les View Helpers.

Module MVC Prestashop 1.5

Pour aller plus loin

Les possibilités offertes par PrestaShop 1.5 en matière de MVC permettent donc de mieux structurer les différents composants back et front office du module, en répartissant les responsabilités au sein de différentes classes.

Le support des Controllers de front office est en très gros plus, et va permettre aux développeurs de personnaliser l’apparence, voire le fonctionnement intégral du front office.

Désormais, les modules sont à concevoir comme des APIs : en effet, chaque Controller de module dispose d’une référence au module, et peut en appeler les méthodes.

Ressources

Si vous souhaitez les étudier, les sources du module sont à disposition sur le GitHub de Prestarocket.

Co-écrit avec @alexmex_, auteur du framework Pan pour Prestashop
  • http://www.strategio.fr/ Strategio

    Excellente explication !
    C’est vrai qu’en utilisant les fonctionnalités de haut niveau de Prestashop, on gagne énormément de temps dans le développement et on s’assure une parfaite intégration des modules dans le back-office.

  • Lucas

    Bonjour,
    Comment faire pour ajouter un CSS d’une page du controler?
     

  • shagshag

    Merci pour cette explication.

    Dans la structure du module il manque le dossier /translations/ qui doit contenir les fichiers fr.php, es.php des traduction du module. Auparavant celles-ci étaient en vrac à la racine du module.

    • http://www.prestarocket.com/ Prestarocket

      Merci pour ta remarque sur les dossiers trad.

      • Vincent Grimaud

        Merci pour ce tuto. Juste une chose, j’ai balayé les différents modules natifs de la 1.5, et très très peu, intègrent la structure que tu mentionnes plus haut (controllers, models, views, translations)… pourquoi ? Cette structure est-elle recommandée par la team ? Merci pour tes eclaircissements.
        Vins.

        • http://www.prestarocket.com/ Prestarocket

          Hello Vincent,

          Cette structure est recommandée par la team Prestashop et apparemment ce tuto est utilisé dans les formations Prestashop.

  • Christophe

    En passant par hookHeader, comme en 1.4 ?

  • Balisong

    Merci pour le tuto mais lorsque j’ai voulu tester le module dispo sur gitHub avec la prestashop 1.5.0.17 finale, cela n’a pas fonctionné.
    L’install du module se fait, je rajoute l’onglet, j’arrive a accéder a la page admin mais lorsque je clique sur “Add new”, la zone centrale est blanche.
    L’ajout d’opinion depuis le front ne fonctionne pas non plus.

    Des idées? Y-at-il eu des motifs sur la version finale qui font que ça ne fonctionne pas?

  • Hervé

    Excellent tuto. Juste un détail pour ceux qui veulent créer les fichiers à la main au fur à mesure au lieu de les prendre tous cuits sur GitHub : Vous ne parlez pas du require_once _PS_MODULE_DIR_.’prcustomeropinion/models/Opinion.php'; qui est nécessaire dans prcustomeropinion.php. Comme controllers/front/default.php ne trouvait pas la classe Opinion, j’ai voulu faire un require ‘../../models/Opinion.php’ et bien entendu ça ne fonctionnait pas. J’ai compris en jetant un oeil au fichier sur GitHub.
    Mais à part ça, merci !

    • http://www.zaibatsu.fr/ Tom Panier

      Normal que ça ne fonctionne pas avec “../../models/Opinion.php” étant donné que prcustomeropinion.php se trouve à la racine du module :) “models/Opinion.php” suffit, et pour faire plus propre : __DIR__.”/models/Opinion.php”

  • http://ehinarr.wordpress.com/ Ehinarr

    Merci. Excellente explication !

  • Sebastien

    Bonjour,

    J’ai repris ce tuto avec les fichiers et j’ai un problème lors du clic sur le bouton pour enregistrer le commentaire. J’ai essayé de trouver l’erreur et elle vient de la methode add().

    Comment est ce possible? Cela marche chez vous? 
    J’ai pris les fichiers qu’il y a sur le site au cas ou et je n’ai pas fais de modification.

    Merci de votre réponse

  • Abdeslam

    Merci bcp, Excellent tuto !

  • Bidule

    c’est le tuto utilisé en formation développeur prestashop ^^…

  • tenuis

    Merci pour ce tuto. Par contre je suis confronté à un problème avec la 1.5.0.17, le changement de langue ne fonctionne pas.

    J’ai adapté le module pour en faire un très simple, qui ne fait qu’afficher le tpl qui se trouve dans /views/templates/front/, mais lors du clic sur la langue, le switch ne se fait pas (pareil pour le module d’opinions installé sans modifs d’ailleurs).
    Pourtant l’adresse s’update correctement avec id_lang qui change, mais le cookie lui reste à l’ancienne valeur.

    Lorsque je change la langue à un autre endroit du site et que je reviens sur la page du module, la langue est la bonne.

    Quelqu’un aurait une solution ?

  • http://www.facebook.com/carpentier.valentin Valentin Carpentier

    Pour ceux qui tombent sur la page blanche lors du clic sur  “Give my opinion” (Sebastien, Hervé, Balisong, etc), voici l’explication : En réalité, c’est la ligne $opinionObj->id_customer = $this->context->customer->id;   du fichier default.php qui pose problème, puisqu’elle demande à prestashop l’id du membre en cours.Alors que vous n’étiez pas connecté. Donc erreur lors de l’insert en base de données.La solution :Remplacer la ligne : if ($_SERVER['REQUEST_METHOD'] == ‘POST’ ) {Par :  if ($_SERVER['REQUEST_METHOD'] == ‘POST’ && Context::getContext()->customer->isLogged()) {

  • diegooo

    Bonjour,

    J’ai suivi le tuto afin de créer un module pour prestashop 1.5.2. Comme certaines personnes ci-dessous, l’ajout d’opinion dans la base ne marche pas, pour une raison que j’ignore.

    J’arrive à accéder à la page de front, à la page d’admin, mais sur ce point … je ne comprends pas !

    Pourriez-vous m’aider svp ?

    Merci d’avance !

    • http://www.facebook.com/junior.lachguel Youssef Lachguel

      l ajout d’opinion au front office n est traité que pour les utilisateurs connectés,essaye avec un utilisateur connecté.
      N.B essaie d’insérer un enregistrement opinion via phpmyadmin pour activer l affichage du module au niveau du front
      Pour fixer l’ajouer d’ opinion via le back office, j ai pas encore fixé le bug

  • diegooo

    Bonjour,

    J’ai suivi le tuto en reprenant les sources présentes sur le github. J’affiche bien la page admin ainsi que le front, mais pas possible d’insérer de données dans la table “opinion” en passant par le formulaire.

    Avez-vous une idée de l’origine du pb ? Je suis en PS 1.5.2, et j’aurais vraiment besoin que cela fonctionne chez moi afin de créer mon propre module :)

    Merci par avance !

    Diego

  • Pingback: Créer un module pour PrestaShop 1.5 » DevNet – Ressources développement web()

  • http://twitter.com/MichelParreno Parreno Michel

    Excellent tuto, c’est bien le seul tuto pour développer des modules 1.5 que j’ai trouvé ! Même sur le site site de Presta c’est l’ancien guide…
    Petite question par contre, j’ai commencé à créer un onglet admin, j’ai bien défini la classe et le module, mais quand je vais sur mon onglet, il n’y a rien (avant il y avait une alerte controller introuvable que j’ai corrigé) mais maintenant il ne m’affiche rien, malgré des lignes dans ma table.
    Une idée de ou ça peut venir ?

  • Arnault

    Bonjour,
    merci pour l’explication assez claire.
    Sauriez vous s’il est possible de définir un controller pour un hook ?
    Exemple : On aurait un formulaire dans le views/hook que l’on souhaiterait traiter.
    Cette situation est d’autant plus vraisemblable qu’il existe un hook DisplayAdminProductsExtra qui rajoute un tab dans l’admin products à l’edition ou à la mise à jour du produit.

  • Vit

    Hello. Excellent tutorial but there are unclear moments. For example : The default ADD button must be handled by an action. How should that action to be named and where it should be placed?

  • Ademus

    Merci pour ce tuto.

    Savez vous comment instancier un controller dans presta 1.5 ? depuis une classe et hors d’une classe ?

    là où avec prest 1.4 on faisait : ControllerFactory::getController(‘

  • bertrand greslier

    Excellent et bien épuré!

  • Pingback: Prestashop - Resolu()

  • http://www.facebook.com/samuel.calegari Samuel Calegari

    Pour ceux qui se posent la question de comment

    gérer le bouton d’ajout dans l’administration il faut rajouter ce code dans le fichier adminopinion.php juste en dessous de $this->fields_list = array(…);

    $this->fields_form = array(

    ‘legend’ => array(
    ‘title’ => $this->l(‘Settings’),
    ),
    ‘input’ => array(
    array(
    ‘type’ => ‘select’,
    ‘label’ => $this->l(‘Customer’),
    ‘name’ => ‘id_customer’,
    ‘required’ => true,
    ‘options’ => array(
    ‘query’ => Customer::getCustomers(),
    ‘id’ => ‘id_customer’,
    ‘name’=>’lastname’
    )
    ),
    array(
    ‘type’ => ‘select’,
    ‘label’ => $this->l(‘Opinion’),
    ‘name’ => ‘opinion’,
    ‘required’ => true,
    ‘options’ => array(
    ‘query’ => array(
    array(
    ‘id’ => ‘Average’,
    ‘name’ => $this->l(‘Average’)
    ),
    array(
    ‘id’ => ‘Good’,
    ‘name’ => $this->l(‘Good’)
    ),
    array(
    ‘id’ => ‘Very Good’,
    ‘name’ => $this->l(‘Very Good’)
    ),
    ),
    ‘id’ => ‘id’,
    ‘name’ => ‘name’
    )
    ),
    array(
    ‘type’ => ‘radio’,
    ‘label’ => $this->l(‘Active’),
    ‘name’ => ‘active’,
    ‘required’ => true,
    ‘class’ => ‘t’,
    ‘br’ => true,
    ‘values’ => array(
    array(
    ‘id’ => ‘0’,
    ‘value’ => 0,
    ‘label’ => $this->l(‘No’)
    ),
    array(
    ‘id’ => ‘1’,
    ‘value’ => 1,
    ‘label’ => $this->l(‘Yes’)
    )
    )
    )
    ),
    ‘submit’ => array(
    ‘title’ => $this->l(‘Save’),
    ‘class’ => ‘button’
    )
    );

  • zlataura

    Bonjour,

    J’ai suivi le tuto en reprenant les sources présentes sur le github, mais j’arrive pas installer le module sur prestashop.
    J’ai l’erreur suivante:
    [PrestaShop] Fatal error in module Opinion:
    syntax error, unexpected ‘–‘ (T_DEC)
    Avez-vous une idée de l’origine du problème ? Je suis en PS 1.5.6.1, et
    j’aurais vraiment besoin que cela fonctionne chez moi afin de créer mon
    propre module :)

    Merci par avance !

  • Pingback: Prestashop | Pearltrees()

  • Prescol

    Thanks a lot! The only complete and usefull information about MVC in modules in prestashop.

  • Pingback: Enfin un très bon livre sur PrestaShop | Prestarocket()