Ajouter un nouveau champ produit personnalisé dans Prestashop n’est pas très compliqué en soit quand on sait où le faire.

L’avantage de cette méthode, c’est quelle peut aussi bien fonctionner sur la version 1.6 de Prestashop que sur la version 1.7.

Nous allons avoir besoin de modifier la classe Produit de Prestashop sous forme d’override ainsi que la partie affichage sur notre formulaire de fiche produit dans la vue. Et ainsi nous permettre de rajouter un nouveau champ produit.

Création de notre module

Pour la première étape, nous allons devoir créer un nouveau module que nous allons nommer composition dans le répertoire /modules/composition.

<?php
if (!defined('_PS_VERSION_')) {
  exit;
}

class Composition extends Module
{
  public function __construct()
  {
    $this->name = 'composition';
    $this->tab = 'others';
    $this->version = '1.0.0';
    $this->author = 'Pascal GAULT';
    $this->need_instance = 0;
    $this->ps_versions_compliancy = [
      'min' => '1.6',
      'max' => _PS_VERSION_
    ];
    $this->bootstrap = true;

    parent::__construct();

    $this->displayName = $this->l('Customize Admin Product');
    $this->description = $this->l('Allows us to add others fields to product');

    $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');
  }
}

Nous allons rajouter quelques méthodes à notre modules, une pour l’installation / désinstallation et une autre pour le hook que nous allons avoir besoin pour modifier notre vue de l’administration des produits.

Après la méthode __construct(), ajoutons donc ces méthodes d’installation.

public function install() {
    if (!parent::install()
    || !$this->_installSql()
    || !$this->registerHook('displayAdminProductsMainStepLeftColumnMiddle') ) { 
        return false; 
    } 
    
    return true; 
}

public function uninstall() {
   return parent::uninstall() && $this->_unInstallSql();
}
protected function _installSql() {
    $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product ADD composition TEXT NULL";
    $returnSql = Db::getInstance()->execute($sqlInstall);
    return $returnSql;
}
protected function _unInstallSql() {
    $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product DROP composition";
    $returnSql = Db::getInstance()->execute($sqlInstall);
 
    return $returnSql;
}

Ici, rien de bien compliqué, nous allons définir que lorsque l’on installe notre module, nous allons modifier la structure de la table ps_product pour y rajouter notre champ produit composition.

Il nous reste une dernière modification dans ce fichier. C’est au niveau du hook pour l’affichage de notre bloc dans le backoffice.

public function hookDisplayAdminProductsMainStepLeftColumnMiddle($params) {
    $product = new Product($params['id_product']);

    $this->context->smarty->assign(array(
      'composition' => $product->composition,
    ));

    return $this->display(__FILE__, 'views/hook/admin/product/extra_fields.tpl');
}

Nous allons donc intervenir au niveau du hook hookDisplayAdminProductsMainStepLeftColumnMiddle pour y injecter notre vue personnalisée.

Création de notre vue personnalisée de champ produit

Suite à l’ajout de notre hook, on créer notre vue personnalisée dans le répertoire /modules/composition/views/hook/admin/product/extra_fields.tpl

<div class="form-group">
  <h4>Composition</h4>
  <div class="translations tabbable">
    <div class="translationsFields tab-content bordered">
      <div class="tab-pane translation-label-fr active">
        <textarea class="rte autoload_rte" name="composition">
          {$composition}
        </textarea>
      </div>
    </div>
  </div>
</div>

Override Champ Produit

Il ne nous reste plus qu’à prévenir Prestashop de notre nouveau champ. En surchargeant la classe du core via une override. Ajoutons un fichier à l’emplacement /override/classes/Product.php avec ce contenu.

<?php
class Product extends ProductCore
{
  public $composition;

  public function __construct(
    $id_product = null,
    $full = false,
    $id_lang = null,
    $id_shop = null,
    Context $context = null
  ) {
    self::$definition['fields']['composition'] = array(
      'type' => self::TYPE_HTML,
      'lang' => false,
      'required' => false,
      'validate' => 'isCleanHtml'
    );

    parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
  }
}

Thème

Au niveau du front, vous avez maintenant la possibilité d’appeler directement $product->composition

En conclusion, vous avez toutes les cartes en main pour ajouter un champ produit personnalisé dans Prestashop. N’hésitez pas à me contacter si vous voulez que l’on fasse cette opération ensemble.

Commentaires

N'hésitez pas à me laisser un petit commentaire pour que l'on discute ensemble de cet article.

  1. Bonjour, merci pour ce tuto super simple à comprendre.
    Cependant, je souhaite intégrer plusieurs champs et pas 1 seul. Mais mes modifications (sur protected function, la fonction hook et product.php font que le module ne parvient pas à s’installer, supposant que les modifs sur extra_fields.tpl n’influence pas l’installation. (je suis novice ne php). comment faire ? Merci

    1. Bonjour,

      Pour rajouter un second champ par exemple, il faut modifier la fonction _installSql() et _unInstallSql() et aussi la classe (override) Product.php. Ce sont les seuls facteurs qui font que le module a du mal à s’installer.

      Je te mets un exemple ci-dessous pour l’ajout d’un second champ :

        protected function _installSql() {
            $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product ADD composition TEXT NULL, ADD monsecondchamp TEXT NULL";
            $returnSql = Db::getInstance()->execute($sqlInstall);
            return $returnSql;
        }
        protected function _unInstallSql() {
            $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product DROP composition, DROP monsecondchamp";
            $returnSql = Db::getInstance()->execute($sqlInstall);
      
            return $returnSql;
        }
      

      Et dans le Product.php :

      <?php
      class Product extends ProductCore
      {
        public $composition;
        public $monsecondchamp;
      
        public function __construct(
          $id_product = null,
          $full = false,
          $id_lang = null,
          $id_shop = null,
          Context $context = null
        ) {
          self::$definition['fields']['composition'] = array(
            'type' => self::TYPE_HTML,
            'lang' => false,
            'required' => false,
            'validate' => 'isCleanHtml'
          );
      
          self::$definition['fields']['monsecondchamp'] = array(
            'type' => self::TYPE_HTML,
            'lang' => false,
            'required' => false,
            'validate' => 'isCleanHtml'
          );
      
          parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
        }
      }
      

      Ça devrait débloquer l’installation de ton module.

    2. Oui parfait ! J’étais sur la bonne voie mais n’avais pas la bonne syntaxe ! Merci beaucoup pour ces explications.
      Martin

  2. Bonjour,
    Ayant suivi votre tuto, j’ai maintenant réussi à ajouter un nouveau champs à mes produits.
    Cependant j’aimerais que le moteur de recherche de Prestashop puisse indexer ce nouveau champs. Pour le moment, lorsque j’effectue une recherche avec des valeurs liées à ce nouveau champs, il n’y a aucun résultat…
    Je voulais donc savoir si vous pouviez m’aider à résoudre ce petit problème ?

    Merci beaucoup pour votre tuto simple et efficace !

    1. Bonjour Gurvan,

      Alors oui c’est tout à fait normal, Prestashop indexe uniquement le contenu qu’il a besoin.

      C’est un sujet assez complexe de rajouter des champs personnalisés dans la recherche mais c’est faisable. Il n’y a pas de hook ou autre pour le faire sans réécrire une partie de la recherche Prestashop.

      L’idée va être d’override la recherche de Prestashop (/classes/Search.php) pour rajouter ton(tes) nouveau(x) champ(s) à l’indexe de Prestashop.

      A partir de là, Prestashop sera au courant de ces nouveaux champs et pourra proposer les produits correspondant côté front à tes utilisateurs.

      Tu dois override trois classes dans ton override Search.php /override/classes/Search.php :

      • getProductsToIndex() : Récupère les produits en fonction des champs
      • indexation() : Moulinette d’indexation Prestashop
      • searchTag() : fonction de recherche de tag

      Tu peux t’inspirer d’une conversation sur le forum de Prestashop qui en parle et qui fonctionne :
      https://www.prestashop.com/forums/topic/618201-adding-product-custom-fields-to-search/

      Je vais faire prochainement un article sur le sujet pour expliquer comment rajouter des champs produits personnalisés à la recherche ce qui permettra de compléter cet article.

      Désolé de ne pas pouvoir t’aider plus pour le moment.

      Bonne journée 😉

    2. Merci beaucoup pour votre réponse. C’est en effet ce que j’ai commencé à faire, mais je ne savais pas exactement quelles classes ajouter dans l’Override.
      Je vais pouvoir continuer grâce à vos explications !
      Encore merci pour votre aide !

  3. Bonjour,

    Merci pour le tutoriel ! Je parviens à ajouter de simples champs textes ainsi que des champs éditeur HTML et à les sauvegarder en deux langues.

    Mais j’aimerais pouvoir ajouter une liste déroulante (les options peuvent être directement saisies en dur dans le template du formulaire avec un label texte et une valeur numéraire qui serait la seule sauvegardée en DB) et n’ai pour l’instant pas vraiment une idée de comment faire.

    Si vous avez le temps pour un exemple, ce serait super !

    D’avance merci 🙂

    1. Bonjour Claire,

      En reprenant l’exemple de l’article, tu as uniquement deux fichiers à modifier pour parvenir à mettre en place une liste déroulante.

      Dans ton fichier de vue /modules/composition/views/hook/admin/product/extra_fields.tpl, il va falloir changer le fonctionnement par quelque chose de la sorte :

      <div class="form-group">
          <h4>Composition</h4>
      
          <select name="composition" class="form-control">
              <option value="1">Première valeur</option>
              <option value="2">Seconde valeur</option>
          </select>
      </div>
      

      Ensuite, dans l’override de la classe Product(/override/classes/Product.php), tu vas devoir retirer la validation ainsi que modifier le type de champ :

      self::$definition['fields']['composition'] = array(
                  'type' => self::TYPE_INT,
                  'lang' => false,
                  'required' => false,
              );
      

      Avec ça, tout devrait fonctionner pour prendre en charge ta liste déroulante.

      Bonne journée

  4. Bonjour Pascal,

    Merci beaucoup pour cette rapide réponse. Cela m’a pris un peu de temps (je débute en PrestaShop, PHP et SQL) parce qu’il faut que je gère une partie des champs en multilingue mais c’est bon j’ai réussi à ajouter la liste et à sauvegarder la valeur dans la table product.

    Si je peux me permettre une autre question, comment puis-je à l’ouverture de la page d’édition d’un produit pré-selectionner la valeur dans la liste avec la valeur que j’ai en DB ? Parce que pour l’instant c’est la première valeur qui s’affiche dans la liste.

    Encore merci !

    1. Pardon j’ai oublié cette partie, tu peux récupérer la valeur courante de la sorte :

      <select name="composition" id="" class="form-control">
        <option value="1" {if $composition == "1"}selected{/if}>Première valeur</option>
        <option value="2" {if $composition == "2"}selected{/if}>Seconde valeur</option>
      </select>
      
  5. Bonjour,

    Merci pour le tutoriel ! Je m’embrouille la pour la création du modules est-ce dans le fichiers modules du racines qu’on le met ou dans le thème. .

  6. Bonjour,
    Merci beaucoup pour ce tutoriel.
    Comment faire pour qu’en Front, dans un fichier .tpl, le {$product.composition} soit interprété en HTML ?

    Merci 🙂

    1. Bonjour,

      C’est assez simple, on peut utiliser une fonction de Smarty qui se nomme nofilter. Car par défaut, Smarty empêche l’injection d’HTML dans la page pour nous proteger d’une attaque XSS

      Tu peux donc afficher ta nouvelle variable sous cette forme :

      {$product.composition nofilter}

      Si tu veux faire les choses encore mieux, tu peux nettoyer le HTML avant de passer le nofilter :

      {$product.composition|cleanHtml nofilter}

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Articles reliés

Retrouvez ci-dessous quelques articles qui pourrait vous intéresser.

WordPress 5.5 - Environnement Type
15
Août

Types d’environnements sous WordPress 5.5

Introduction à la nouvelle fonction wp_get_environnement_type() sur WordPress 5.5 nous permettant de savoir sur quel type d’environnement on se trouve. Très pratique pour les développeurs de thèmes ou de plugins d’effectuer des tâches précises en fonction du type d’environnement.

Voir plus