Prestashop 1.7 : Ajouter des champs dans le listing produit admin

Ce tutoriel est compatible avec les versions de Prestashop suivantes :
1.6 1.7 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 8.0 8.1 +
Cet article est assez ancien, malgré toute l'attention que j' apporte à mes contenus il est possible que celui-ci ne soit plus d'actualité.
N'hésitez pas à me le signaler si nécessaire via le formulaire de contact.

A la suite de mon précédent article sur comment ajouter des champs produits dans l’administration de prestashop 1.7 : https://www.h-hennes.fr/blog/2017/10/19/prestashop-1-7-ajouter-des-champs-produit/ , nous allons à présent voir comment ajouter des champs dans le listing des produits de l’administration.

Cette page est gérée via les nouveaux controllers symfony et leur fonctionnement est donc différents des autres listing de l’administration.

 

Je ne détaille pas la base de la création du module qui pourra reprendre celle de l’article sur la création des champs produits.

Le module devra implémenter les hooks suivants :

  • actionAdminProductsListingFieldsModifier (hook natif )
  • displayAdminCatalogTwigListingProductFields ( hook custom)
  • displayAdminCatalogTwigProductFilter ( hook custom )
  • displayAdminCatalogTwigProductHeader ( hook custom )

Pour l’exemple nous allons ajouter un filtre sur les marques des produits, mais la logique s’applique à n’importe quel champ.

Modification des fichiers twigs pour la création des nouveaux hooks

Prestashop 1.7.2.x et inférieurs :

Avec les versions 1.7.2.x et inférieures il n’est pas possible de réaliser cette modification sans toucher à des fichiers « coeur » puisque la surcharge des templates symfony n’est pas encore gérée via les modules.

Pour autant la solution que je propose reste assez propre les seules lignes qui seront ajoutées le seront pour ajouter un appel de hook.

Les templates utilisés pour le listing des produits seront donc les suivants :

  • src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
  • src\PrestaShopBundle\Resources\views\Admin\Product\list.html.twig

Prestashop 1.7.3.x et supérieur :

A partir de cette version il est possible de surcharger facilement les templates depuis votre module.
Vous pouvez trouver la source de l’information  sur le gist de Mickäel Andrieu : https://gist.github.com/mickaelandrieu/4a02ea05bb1113718aec5432ad418ee5
Dans notre cas il faut créer les fichiers de templates suivant dans le module

  • views/PrestaShop/Admin/Product/catalog.html.twig
  • views/PrestaShop/Admin/Product/list.html.twig

Vous pouvez reprendre l’intégralité du contenu des fichiers sources  et y appliquer les mêmes modifications.

Dans catalog.html.twig :

Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher des colonnes supplémentaires #}
 {{ renderhook('displayAdminCatalogTwigProductHeader') }}

Après le code :

 <th>
 {{ "Category"|trans({}, 'Admin.Catalog.Feature') }}
 {% include 'PrestaShopBundle:Admin/Product/Include:catalog_order_carrets.html.twig' with {
 'column': 'name_category'
 } %}
 </th>

Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher des filtres supplémentaires #}
 {{ renderhook('displayAdminCatalogTwigProductFilter') }}

Après le code :

 <th>
 <input
 type="text"
 class="form-control"
 placeholder="{{ "Search category"|trans({}, 'Admin.Catalog.Help') }}"
 name="filter_column_name_category"
 value="{{ filter_column_name_category }}"
 />
 </th>

Dans list.html.twig :
Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher les nouveaux champs dans le listing #}
 {{ renderhook('displayAdminCatalogTwigListingProductFields', { 'product': product }) }}

Après le code :

 <td>
 {{ product.name_category|default('') }} 
 </td>

Affichage des nouveaux champs via les hooks du fichier twig

Nos nouveaux hooks étant maintenant créé il est temps d’ajouter nos champs via les hooks du module :

hook displayAdminCatalogTwigProductHeader : Affichage de l’entête de la colonne

 /**
 * Hook personnalisé ( non core ) pour afficher le header product
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
 * @param type $params
 */
 public function hookDisplayAdminCatalogTwigProductHeader($params)
 {
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigProductHeader.tpl'); 
 }

Contenu du fichier displayAdminCatalogTwigProductHeader.tpl :

 <th>{l s='Manufacturer' mod='hhproduct'}</th>

 

hook displayAdminCatalogTwigProductFilter : Affichage du champ html du filtre

 /**
 * Hook personnalisé ( non core ) pour afficher le filter product
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
 * @param type $param
 */
 public function hookDisplayAdminCatalogTwigProductFilter($params)
 {
 $manufacturers = Manufacturer::getManufacturers();
 $this->context->smarty->assign(
 [
 'filter_column_name_manufacturer' => Tools::getValue('filter_column_name_manufacturer',''),
 'manufacturers' => $manufacturers,
 ]
 );
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigProductFilter.tpl');
 }

Contenu du fichier displayAdminCatalogTwigProductFilter.tpl :

 <th>
 <select name="filter_column_name_manufacturer" data-toggle="select2">
 <option value="">{l s='Manufacturer' mod='hhproduct'}</option>
 {foreach from=$manufacturers item=manufacturer}
 <option value="{$manufacturer.id_manufacturer}" 
 {if $filter_column_name_manufacturer == $manufacturer.id_manufacturer} selected="selected"{/if}>
 {$manufacturer.name}
 </option>
 {/foreach}
 </select>
</th>

 

hook displayAdminCatalogTwigListingProductFields : Affichage de la valeur du champ pour chaque produit

 /**
 * Hook personnalisé (non core) pour afficher les informations additionnelles produits )
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\list.html.twig
 * @param type $params
 */
 public function hookDisplayAdminCatalogTwigListingProductFields($params)
 {
 $this->context->smarty->assign('product',$params['product']);
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigListingProductFields.tpl');
 }

Contenu du fichier displayAdminCatalogTwigListingProductFields.tpl :

 <td>{$product.manufacturer}</td>

 

Avec ces codes nous devrions à présent obtenir l’affichage suivant :

Prestashop produt fields

C’est bien joli mais il n’y a pas de données 😉

 

Affichage et filtrage des résultats

Pour remonter ces données la bonne nouvelle c’est que le hooks natif de prestashop 1.6 fonctionne encore !
Dans le fichier \src\Adapter\Product\AdminProductDataProvider.php, le hook actionAdminProductsListingFieldsModifier est toujours appellé.
Comme vous pouvez le voir ligne 280

 // exec legacy hook but with different parameters (retro-compat < 1.7 is broken here)
 \HookCore::exec('actionAdminProductsListingFieldsModifier', array(
 '_ps_version' => _PS_VERSION_,
 'sql_select' => &$sqlSelect,
 'sql_table' => &$sqlTable,
 'sql_where' => &$sqlWhere,
 'sql_order' => &$sqlOrder,
 'sql_limit' => &$sqlLimit,
 ));

Voici donc l’implémentation du hook dans notre module :

/**
* Modification de la requête de la liste
* @param type $params
*/
public function hookActionAdminProductsListingFieldsModifier($params)
{
/**
* Rajout du fabricant
*/
//Champ sql
$params['sql_select']['manufacturer'] = [
'table' => 'm',
'field' => 'name',
'filtering' => \PrestaShop\PrestaShop\Adapter\Admin\AbstractAdminQueryBuilder::FILTERING_LIKE_BOTH
];
//Table sql
$params['sql_table']['m'] = [
'table' => 'manufacturer',
'join' => 'LEFT JOIN',
'on' => 'p.`id_manufacturer` = m.`id_manufacturer`',
];
 
//Gestion du filtre, si un paramètre post est défini ( c'est le nom du champ dans le fichier displayAdminCatalogTwigProductFilter.tpl )
$manufacturer_filter = Tools::getValue('filter_column_name_manufacturer',false);
if ( $manufacturer_filter && $manufacturer_filter != '') {
$params['sql_where'][] .= "p.id_manufacturer =".$manufacturer_filter;
}
}

Voici donc comment rajouter et filtrer les résultats de l’attribut manufacturer 🙂

Et voici le rendu final, avec le filtre qui fonctionne :

Colonne manufacturer OK

 

EDIT 2018-03-20 : Ajout des informations pour PS 1.7.3 et supérieur

35 réflexions sur “Prestashop 1.7 : Ajouter des champs dans le listing produit admin”

  1. Hi, and thanks for your tutorials, but with this I’m stuck, I’ve come up here
    Après the queues:

     
      {{product.name_category | default ( »)}}
     

    but from this point

    Affichage des nouveaux champs via les hooks du fichier twig

    Nos nouveaux hooks étant maintenant créé the east temps d’ajouter nos champs via les hooks du module:

    hook displayAdminCatalogTwigProductHeader: Affichage de l’entête de la columns

    I can not figure out how to proceed,

    you can help me understand better please

    1. Hello,

      With this phrase i mean that the module has to be attached to these specifics hooks.
      This can be done by :

      – add module to hook in install method ( with $this->registerHook(‘hookName’)
      – implement hook method in class ( with function hookHookName() )

      It’s a prestashop basic concept 🙂

      Regards,
      Hervé

  2. I have tried using this script on my 1.7.2 PS store

    It works with one exception

    When « filtering » the manufacturer I i insert a name say « superdry » it shows only the superdry products.

    However if the number of products returned exceeds what is displayed on the page so i have to click page 2 on the pagination it reverts back as if there is no filter in place at all

    any suggestions>?

  3. Bonjour

    Site très utile en tout cas

    J’ai un petit soucis c’est que j’ai une version 1.7.1 de prestashop

    Comment faire pour adapter ce module pour qu il marche avec ma version ?

    merci par avance

  4. J’ai juste fait comme vous avez dis
    modifier les 2 fichiers twig

    et crée le module
    ————————–

    name = ‘adminlistproducts’;
    $this->tab = ‘others’;
    $this->author = ‘hhennes’;
    $this->version = ‘0.1.0’;
    $this->need_instance = 0;
    $this->bootstrap = true;

    parent::__construct();

    $this->displayName = $this->l(‘adminlistproducts’);
    $this->description = $this->l(‘add new fields to product list’);
    $this->ps_versions_compliancy = array(‘min’ => ‘1.7.0’, ‘max’ => _PS_VERSION_);

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

    if (!Configuration::get(‘adminlistproducts’))
    $this->warning = $this->l(‘No name provided’);
    }

    public function install() {
    if (!parent::install()
    //Pour les hooks suivants regarder le fichier src\PrestaShopBundle\Resources\views\Admin\Product\form.html.twig
    || ! $this->registerHook(‘displayAdminCatalogTwigProductHeader’)
    || ! $this->registerHook(‘displayAdminCatalogTwigProductFilter’)
    || ! $this->registerHook(‘displayAdminCatalogTwigListingProductFields’)
    || ! $this->registerHook(‘actionAdminProductsListingFieldsModifier’)
    ) {
    return false;
    }

    return true;
    }

    public function uninstall() {
    return parent::uninstall() ;
    }

    public function hookDisplayAdminCatalogTwigProductHeader($params)
    {
    return $this->display(__FILE__,’views/templates/hook/displayAdminCatalogTwigProductHeader.tpl’);
    }

    public function hookDisplayAdminCatalogTwigProductFilter($params)
    {
    $manufacturers = Manufacturer::getManufacturers();
    $this->context->smarty->assign(
    [
    ‘filter_column_name_manufacturer’ => Tools::getValue(‘filter_column_name_manufacturer’, »),
    ‘manufacturers’ => $manufacturers,
    ]
    );
    return $this->display(__FILE__,’views/templates/hook/displayAdminCatalogTwigProductFilter.tpl’);
    }

    public function hookDisplayAdminCatalogTwigListingProductFields($params)
    {
    $this->context->smarty->assign(‘product’,$params[‘product’]);
    return $this->display(__FILE__,’views/templates/hook/displayAdminCatalogTwigListingProductFields.tpl’);
    }

    /**
    * Modification de la requête de la liste
    * @param type $params
    */
    public function hookActionAdminProductsListingFieldsModifier($params)
    {
    /**
    * Rajout du fabricant
    */
    //Champ sql
    $params[‘sql_select’][‘manufacturer’] = [
    ‘table’ => ‘m’,
    ‘field’ => ‘name’,
    ‘filtering’ => \PrestaShop\PrestaShop\Adapter\Admin\AbstractAdminQueryBuilder::FILTERING_LIKE_BOTH
    ];
    //Table sql
    $params[‘sql_table’][‘m’] = [
    ‘table’ => ‘manufacturer’,
    ‘join’ => ‘LEFT JOIN’,
    ‘on’ => ‘p.`id_manufacturer` = m.`id_manufacturer`’,
    ];

    //Gestion du filtre, si un paramètre post est défini ( c’est le nom du champ dans le fichier displayAdminCatalogTwigProductFilter.tpl )
    $manufacturer_filter = Tools::getValue(‘filter_column_name_manufacturer’,false);
    if ( $manufacturer_filter && $manufacturer_filter !=  ») {
    $params[‘sql_where’][] .= « p.id_manufacturer = ».$manufacturer_filter;
    }
    }

    }

    —————————
    + les 3 hooks .tpl

  5. désolé pour la réponse tardive
    Dans le menu apparence > positions
    J’ai le module qui est accroché sur :
    – displayAdminCatalogTwigListingProductFields
    – displayAdminCatalogTwigProductFilter
    – displayAdminCatalogTwigProductHeader

    mais toujours pas visible ….

  6. Ha et je viens de voir en cochant : Afficher les points d’accroche invisibles
    que le module est bien aussi sur – ActionAdminProductsListingFieldsModifier

  7. Remontage de post :p Quelqu’un a trouvé le soucis ? Idem ici le hook est bien présent dans le BO, mais impossible de l’afficher dans le TPL Twig. C’est bien le TPL du module qui est appelé mais le contenu du TPL du hook non.

    Merci

  8. Bonjour,

    J’ai mon module qui fonctionne sur mon wamp en local mais quand je bascule en ligne il fonctionne pas (tant pis je vais essayer de chercher pourquoi).

    Par contre j’aurais voulu savoir ou je pourrais voir pour réussir à faire un filtre du même type que Référence déjà existant (j’ai rajouté moi même un champ dans produits).

    1. Quand cela ne fonctionne pas en ligne pensez à vider le cache 😉
      Pour votre seconde question , de ce que j’en comprends il faut faire la même chose que l’exemple décrit pour les fabricants.

      Cordialement,
      Hervé

  9. Effectivement il y avait du cache, mais surtout même en 1.7.3 l’override des fichier twig ne sont pas pris en compte (tandis que sur mon local oui). Tant pis je modifie les fichier twig à la mains.

    Le soucis c’est dans la partie displayAdminCatalogTwigListingProductFields.tpl
    Dans le hook je ne comprend pas à quel moment on y affecte le manufacturer (pourtant bien afficher côté front avec le $product.manufacturer).

    Je cherche vraiment à reproduire la même chose que pour référence (c’est un champs texte filtrable en texte et non en liste déroulante).

    Je n’arrive pas à trouver dans les fichier de prestashop à quel moment il affecte la donnée reference et à quel moment il fait son filtre.

  10. Hi,

    I’m trying to show a new column with the accumulated sales for each product:

    // Sold
    $params[‘sql_select’][‘sold’] = [
    ‘table’ => ‘sold’,
    ‘field’ => ‘product_quantity’,
    ‘filtering’ => \PrestaShop\PrestaShop\Adapter\Admin\AbstractAdminQueryBuilder::FILTERING_LIKE_BOTH
    ];

    $params[‘sql_table’][‘sold’] = [
    ‘table’ => ‘order_detail’,
    ‘join’ => ‘LEFT JOIN’,
    ‘on’ => ‘p.`id_product` = sold.`product_id`’,
    ];

    $sold_filter = Tools::getValue(‘filter_column_name_sold’,false);
    if ($sold_filter && $sold_filter !=  ») {
    $params[‘sql_where’][] .=  » p.id_product = « .$sold_filter;
    }

    Now is showing a row by product and sale. I need to modify the query to add a SUM modifier.

    How can achieve that? Thanks in advance and thanks by this tutorial!

  11. Please does anyone has link to github or somewhere to download this? I cant speak French and I really need this :(((((
    Thanks!!

    1. Hi Pavel,
      This article shows a POC ( proof of concept) which show how to add a field to admin listing.
      It is not really intended to be a distribuable module, that’s why it is not available on github 😉

      Regards,

    1. Bonjour,
      Effectivement le code bouge pas mal dans la version 1.7 de prestashop je n’ai pas testé le fonctionnement sur la dernière version. Je rajoute ça dans ma todo mais je manque de temps en ce moment
      Cordialement,

  12. Avant tout, pardon par mon français, il y a ans que je ne parle pas l’idiome.

    Et merci beaucoup par ton article, il est très difficile de trouver information.

    J’ai entendu que pour faire un « override » pour admin twig templates, nous devons copier les archives sur la route /views/Prestashop/Admin/Product/…., mais, comme faire pour indiquer a Prestashop qu’il doit utiliser nôtres archives au lieu des originaux? On doit utiliser quelque hook, ou comme on peut faire?

    Merci beaucoup!

    1. Bonjour,
      Désolé du délai de réponse.
      N’hésitez pas à poser vos questions en anglais si vous le maîtrisez mieux.
      Dès lors que votre module sera installé la sucharge de ces éléments sera prise en compte
      ( Attention car seul un module peut surcharger le fichier à la fois )

  13. I am using 1.7.6.7. created modules like your data with the custom hooks.
    But the fields don’t appear on the page.
    I register the custom hook in the module install function. is the right way to create a custom hook?

  14. Bonjour,
    merci beaucoup pour votre tuto.Super intérréssant.
    Petite question cependant… avez-vous une méthode pour gérer la pagination dans ce cas.
    Si je change de page, le filtre ne fonctionne plus.
    Merci à vous

  15. Bonjour,

    Merci beaucoup pour ce tuto simple et efficace.
    Pour info sur PrestaShop 1.7.6.2 les templates à surcharger ne sont pas exactement les mêmes, il s’agit de : src\PrestaShopBundle\Resources\views\Admin\Product\CatalogPage\Lists\product_table.html.twig et src\PrestaShopBundle\Resources\views\Admin\Product\CatalogPage\Lists\list.html.twig

  16. Teddy Perissinotto

    Bonjour,

    Merci pour ce tuto qui m’a bien aidé.
    Mais hélas, je rencontre un problème avec la pagination.
    Au changement de page, le filtre revient vide.

    Avez-vous une solution ?

    Cordialement

  17. Bonjour,
    Est-il possible d’insérer un champ supplémentaire dans la page des commandes de la même façon ? Je ne trouve pas de trace là dessus sur internet. Nous aimerions mettre sur notre backoffice une colonne des transporteurs.
    Cordialement,

  18. Merci Hervé pour ce tuto. En me basant sur un code trouvé sur le blog de Arnaud Merigneau, j’ai créé un petit module me permettant d’ajouter des dates de péremption sur la fiche produit, et j’aimerais afficher ces dates dans la liste des produits en admin. Je cherche comment mettre ça à la place de $manufacturers dans public function hookDisplayAdminCatalogTwigProductFilter sachant que le nom du champ est custom_field_date et qu’il est dans la table product_lang ?
    Si jamais vous passez par là et avez quelques instants pour me donner une piste, ce serait vraiment très gentil !
    Merci d’avance

Laisser un commentaire

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