Comment ajouter un champ dans une fiche produit Prestashop ?

Prestashop 1.7.6

Difficulté 3/4

Durée 20′

Exemple : ajouter un champ texte dans une fiche produit (onglet)

Vous avez besoin de compléter une description produit par l’ajout d’un onglet supplémentaire ? Prestashop fournit par défaut deux champs description wyswyg (Récapitulatif & Description) mais cela est souvent insuffisant. En effet, il arrive fréquemment que l’on souhaite apporter des informations complémentaires sur un produit sans vouloir surcharger les champs présents. Dans ce tutoriel, nous allons voir les étapes importantes pour ajouter un nouveau champ à la fiche produit. Attention : dans le cas d’un ajout de champ multi-langues, la classe Product de Prestashop ne le gère pas correctement dans le cas d’un simple override, et la sauvegarde en base de données ne se fait pas. Pas de panique, nous avons la solution, dans cet exemple votre sauvegarde fonctionnera que vous soyez en boutique simple, en multishop avec ou sans multilang! Ce module fonctionne à partir de la version 1.7.6 de Prestashop car nous utilisons le nouveau système de traduction. Néanmoins il reste compatible à partir de la version 1.7.0 jusqu’à la version 1.7.6 si vous utilisez l’ancienne méthode de traduction.

Étapes essentielles

pour aboutir à ce résultat il faudra :

  1. créer un module,
  2. ajouter un champ à la table ps_product_lang lors de l’installation du module,
  3. 2 hooks et 3 en multilang,
  4. faire un override de la classe Product,
  5. un template pour la partie back-office.

 

1/ Création du module

Rien de bien sorcier, comme l’indique la documentation de Prestashop un module à besoin pour fonctionner d’avoir un nom de dossier, un fichier .php et une classe portant le même nom. Il devra comporter une méthode de construction, une autre d’installation et une de désinstallation. Lien vers la documentation développeur 1.7 de Prestashop. Par ailleurs il est très important de suivre l’architecture souhaitée par Prestashop pour les créations de modules. Lien vers l’architecture souhaité par Prestashop. Ci-dessous notre création de module csoft_add_field.php.

<?php

class Csoft_add_field extends Module {
  public function __construct() {
    $this->name                   = 'csoft_add_field';
    $this->version                = '1.0.0';
    $this->author                 = 'ComonSoft';
    $this->bootstrap              = true;
    $this->ps_versions_compliancy = array(
      'min' => '1.7.8',
    );
    parent::__construct();
    $this->displayName      = $this->trans('Add wysiwyg field to product page', [], 'Modules.Csoftaddfield.Info');
    $this->description      = $this->trans('Add a wysiwyg text field in product back-office and display  it in the product page', [], 'Modules.Csoftaddfield.Info');
    $this->confirmUninstall = $this->trans('Are you sure you want to uninstall?', [], 'Modules.Csoftaddfield.Info');
  }

  /**
  * Module install
  */
  public function install() {
    return parent::install()
    && $this->_installSql()
    && $this->registerHook('displayAdminProductsMainStepLeftColumnMiddle')
    && $this->registerHook('displayProductExtraContent')
    && $this->registerHook('actionProductSave');  
  }

  /**
  * Module uninstall
  */
  public function uninstall() {
    return parent::uninstall() && $this->_unInstallSql();
  }

   /**
    * For using new translation system
   */
   public function isUsingNewTranslationSystem() {
     return true;
   }

2/ Ajouter un champ à la table ps_product_lang

Afin d’ajouter un champ à la table ps_product_lang, il suffit de faire une requête SQL et de l’appeler au niveau de la méthode d’installation du module. Faire de même avec la désinstallation. ci-dessous la méthode utilisant le nouveau système de traduction et les méthodes d’ajout et suppression du champ cstextfield dans la table ps_product_lang.

  /**
   * SQL module Modifications
   * @return boolean
   */
  protected function _installSql() {
    $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product_lang ADD cstextfield TEXT NULL";
    $returnSql = Db::getInstance()->execute($sqlInstall);
    return $returnSql;
  }

  /**
   * Suppression des modification sql du module
   * @return boolean
   */
  protected function _unInstallSql() {
    $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product_lang DROP cstextfield";
    $returnSql = Db::getInstance()->execute($sqlInstall);
    return $returnSql;
  }

3/ Hooks utilisés en simple et multi-langues

Voici les hooks que nous avons utilisés ici :

  • hookDisplayProductExtraContent (front office)
  • hookDisplayAdminProductsMainStepLeftColumnMiddle (back office)
  • hookActionProductSave (back office pour le multishop)
ci-dessous le code des trois hooks utilisés.

Partie back office hook displayAdminProductsMainStepLeftColumnBottom

Dans notre exemple nous avons utilisé le hook displayAdminProductsMainStepLeftColumnBottom qui permet d’afficher le champ supplémentaire dans la colonne de gauche en dessous des champs existants Résumé et Description

/**
  * Hook for display in product page (back office)
  */
  public function hookDisplayAdminProductsMainStepLeftColumnMiddle($params)
  {
    $product = new Product($params['id_product']);
    $languages = Language::getLanguages(true, (int)Context::getContext()->shop->id);
    $this->context->smarty->assign(
      array(
        'cstextfield' => $product->cstextfield,
        'languages' => $languages,
        'default_language' => $this->context->employee->id_lang,
      )
    );
    return $this->display(__FILE__, 'views/templates/hook/add_field.tpl');
  }

  /**
  * Hook for save in DB after submit in product page (back office)
  */
  public function hookActionProductSave($params) {
    $multistoreFeature = $this->get('prestashop.adapter.feature.multistore');
    $shopContext = $this->get('prestashop.adapter.shop.context');
    $customFieldValue = $params['product']->cstextfield;   

    if ($isMultistoreEnabled = $multistoreFeature->isActive()) {
      if ($isMultistoreUsed = $multistoreFeature->isUsed()){
        $shopList = $shopContext->getShops(false, true);
        foreach ($shopList as $shop) {  
          $languages = Language::getLanguages(true, $shop, false);
          foreach ($languages as $language){
            $sql = Db::getInstance(_PS_USE_SQL_SLAVE_)->execute('UPDATE '. _DB_PREFIX_.'product_lang SET cstextfield = \''
            .pSQL($customFieldValue[$language['id_lang']], true)."'"
            .' WHERE id_shop =' . (int)$shop .' AND id_lang =' .$language['id_lang'].' AND id_product =' .$params['id_product']);
          }
        }
      }
    }
  }
visuel back office:
visuel du hook dans le back office
Copie d’écran mettant en avant notre nouveau champ dans la fiche produit.

Partie front office hook displayProductExtraContent

 /**
  * Hook for display in product page (front office)
  */
  public function hookDisplayProductExtraContent($params) {
    $return = [];
    $return[] = (new PrestaShop\PrestaShop\Core\Product\ProductExtraContent())
    ->setTitle('my field')
    ->setContent($params['product']->cstextfield);
    return $return;
  }
}
Visuel front office :
visuel du hook dans le front office :

4/ Override de la classe Product

Cet override nous permet de définir le type de champ que nous souhaitons ajouter à la classe Product. Ici nous avons ajouté un champ wysiwyg. Ce champ nécessite 3 paramètres : type, lang et validate. ce fichier doit porter le nom de la classe qu’il override et être placé dans dossier override du module.   ci-dessous le code de l’override de la classe Product

<?php
class Product extends ProductCore {
 public $cstextfield;
 public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, \Context $context = null) {
     //Définition des nouveaux champs
     self::$definition['fields']['cstextfield'] = [
         'type' => self::TYPE_HTML,
         'lang' => true,
         'validate' => 'isCleanHtml'
     ];
     parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
 }
}

5/ Template pour la partie back-office

Dans le but d’afficher notre champ wysiwyg  dans le back office il est important de suivre une architecture particulière et d’appeler les classes css indispensables à son bon fonctionnement. Ci-dessous le code de notre template à placer dans le dossier views/templates/hook de votre module.

<div class ="row">
    <div class="col-md-12 left-column">
        <div class='summary-description-container'>
            <h2 class="form-control-label">{l s='My extra description' d='Modules.Csoftaddfield.Admin'}</h2>
            <div id="cstextfield" class="mb-3">
                <div class="translations tabbable">
                    <div class="translationsFields tab-content">
                    {foreach from=$languages item=language}
                        <div class="translation-field translation-label-{$language.iso_code}  translation-label-{$language.id_lang} 
                        {if $default_language == $language.id_lang}show active{/if}" data-locale="{$language.iso_code}">
                            <textarea name="cstextfield_{$language.id_lang}" class="autoload_rte">
                                {if isset({$cstextfield[$language.id_lang]}) && {$cstextfield[$language.id_lang]} != ''}{$cstextfield[$language.id_lang]}{/if}
                            </textarea>
                        </div>
                    {/foreach}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

 

Conclusion

Vous savez maintenant comment ajouter un nouveau champ sur une fiche produit que vous soyez dans un contexte de de multi-langues. Il vous sera désormais facile de personnaliser vos fiches produits pour qu’elles collent exactement à vos souhaits !   A la recherche de modules pour Prestashop Vous avez besoin d’un module sur mesure ou d’un développement particulier ? N’attendez plus  

A bientôt pour de nouveaux tutoriels avec Com’onsoft !