Prestashop : Modifier les listings dans l’administration

Ce tutoriel est compatible avec les versions de Prestashop suivantes :
1.6 1.7 1.7.6 +
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.

En complément d’un de mes précédents articles sur comment ajouter des nouveaux champs dans le listing des produits ( pour prestashop 1.7 ), nous allons voir comment effectuer cette action sur les autres controllers de l’administration.

Les listing des controllers concernés sont ceux qui utilisent encore l’ancienne infrastructure et les anciennes méthodes ( Clients, adresses, commandes , employés … )

Ce tutoriel fonctionne à partir de la version 1.6.0.2 de Prestashop et utilise le hook dynamique action.$this->controller_name.ListingFieldsModifier

Pour les versions inférieures il sera nécessaire de faire un override du controller concerné et d’ajouter les informations directement à la suite des paramètres de classe
$this->_select,
$this->_join,
$this->_where

Exécuté par via le code suivant dans la fonction getList de la classe AdminController

Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array(
'select' => &$this->_select,
'join' => &$this->_join,
'where' => &$this->_where,
'group_by' => &$this->_group,
'order_by' => &$this->_orderBy,
'order_way' => &$this->_orderWay,
'fields' => &$this->fields_list,
));

Les paramètres sont passés par référence au hook ce qui permets de modifier directement les variables qui seront appellées depuis un module.

Les éléments select, join, where, group_by, order_by , order_way permettent de modifier la requête de récupération de la liste des entités.
Alors que le champ fields est un tableau qui regroupe l’ensemble des colonnes qui seront affichées dans la liste.

Pour tester tout cela nous allons faire un module hh_admin dont le but sera le suivant :

– Ajouter 2 nouvelles colonnes dans le listing des clients et supprimer 2 existants :

Le module devra donc implémenter le hook suivant :

  • actionAdminCustomersListingFieldsModifier

Pour modifier le listing client le contenu sera le suivant :

    /**
     * Ajout de champs dans le listing des clients
     * @param type $params
     */
    public function hookActionAdminCustomersListingFieldsModifier($params)
    {
        //Pour l'exemple on va ajouter 2 champs dans le listing
 
        // champ simple texte : date d'inscription à la newsletter ( newsletter_date_add dans la table customer )
        $params['fields']['newsletter_date_add'] = array(
            'title' => $this->l('Date souscription Newsletter')
        );
 
        //Champ un peu plus "complexe" groupe par défaut  select ( id_default_group dans la table customer et récupération des noms des groupes via une jointure )
        $params['select'] .= ' ,grl.name as default_group_name '; //Ajout du champ dans la requête select
        $params['join'] .= 'LEFT JOIN '._DB_PREFIX_.'group_lang grl ON (a.id_default_group = grl.id_group )'; //Jointure avec la table des groupes
 
	//Récupération de la liste des groupes via la méthode prestashop + création d'un tableau sous la forme id_group => name 
	$groups = Group::getGroups($this->context->language->id); 
        $groupsList = array();
        foreach( $groups as $group)
            $groupsList[$group['id_group']] = $group['name'];
 
        //Ajout du nouveau champ à afficher dans le listing
        $params['fields']['default_group_name'] = array(
            'title' => $this->l('Groupe par défaut'),
            'type' => 'select',
            'list' => $groupsList,
            'filter_key' => 'a!id_default_group' //Clé de filtrage dans la requête sous la forme "NomTable!champ"  
        );
 
	//Suppression des champs "Titre","Optin"
        unset($params['fields']['title']);
        unset($params['fields']['optin']);
    }

Une fois le code implémenté nous voyons bien nos 2 nouvelles colonnes dans la liste et les 2 anciennes ont bien disparu.
Tout est fonctionnel sans la moindre surcharge 🙂



Bonus :
Une demande récurrente est également de pouvoir placer les nouveaux champs à un autre endroit qu’a la fin.

Pour cela j’ai créé la fonction suivante :

    /**
     * Ajout du nouveau champ après un autre 
     * @param type $fieldParams
     * @param type $afertName
     * @param type $fieldsArray
     */
    public function addNewFieldAfter($fieldParams,$afterName,array &$fieldsArray)
    {
 
        if (array_key_exists($afterName, $fieldsArray)) {
            $pos = array_search($afterName, array_keys($fieldsArray));
            $before = array_slice($fieldsArray,0,$pos+1);
            $after = array_slice($fieldsArray, $pos); 
            $fieldsArray = array_merge($before,$fieldParams,$after);
 
        } else {
            $fieldsArray = array_merge($fieldsArray,$fieldParams);
        }
    }

Il est possible de l’utiliser de cette manière :

 /**
     * Ajout de champs dans le listing des clients
     * @param type $params
     */
    public function hookActionAdminCustomersListingFieldsModifier($params)
    {
 
        $newField = array( 'default_group_name' => 
		array(
            'title' => $this->l('Groupe par défaut'),
            'type' => 'select',
            'list' => $groupsList,
            'filter_key' => 'a!id_default_group' //Clé de filtrage dans la requête sous la forme "NomTable!champ" 
            )
        );
 
        $this->addNewFieldAfter($newField, 'lastname', $params['fields']);
 
    }

Voici le code code complet du module :

<?php
class HhAdmin extends Module {
 
    public function __construct() {
        $this->name = 'hhadmin';
        $this->tab = 'others';
        $this->author = 'hhennes';
        $this->version = '0.1.0';
        $this->need_instance = 0;
        $this->bootstrap = true;
 
        parent::__construct();
 
        $this->displayName = $this->l('hhadmin');
        $this->description = $this->l('hhadmin description');
        $this->ps_versions_compliancy = array('min' => '1.7.0', 'max' => _PS_VERSION_);
    }
 
    /**
     * @return boolean
     */
    public function install() {
        if (!parent::install() 
                || !$this->registerHook('actionAdminCustomersListingFieldsModifier')      
        ) {
            return false;
        }
 
        return true;
    }
 
    /**
     * Ajout de champs dans le listing des clients
     * @param type $params
     */
    public function hookActionAdminCustomersListingFieldsModifier($params)
    {
        //Pour l'exemple on va ajouter 2 champs dans le listing
 
 
        // champ simple texte : date d'inscription à la newsletter ( dans la table customer )
        $params['fields']['newsletter_date_add'] = array(
            'title' => $this->l('Newsletter subscribe date')
        );
 
        //Champ un peu plus "complexe" groupe par défaut  select ( id_default_group dans la table customer 
        //et récupération des noms des groupes via une jointure )
        $params['select'] .= ' ,grl.name as default_group_name '; //Ajout du champ dans la requête select
        $params['join'] .= 'LEFT JOIN '._DB_PREFIX_.'group_lang grl ON (a.id_default_group = grl.id_group )'; //Jointure avec la table des groupes
        $groups = Group::getGroups($this->context->language->id); //Récupération de la liste des groupes
 
        $groupsList = array();
        foreach( $groups as $group)
            $groupsList[$group['id_group']] = $group['name'];
 
       //Affichage du nouveau champ ( méthode standard)
        /*$params['fields']['default_group_name'] = array(
            'title' => $this->l('Groupe par défaut'),
            'type' => 'select',
            'list' => $groupsList,
            'filter_key' => 'a!id_default_group' //Clé de filtrage dans la requête sous la forme "NomTable!champ"  
        );*/
 
		//Ajout du nouveau champ dans une certaine position
        $newField = array( 'default_group_name' => array(
            'title' => $this->l('Groupe par défaut'),
            'type' => 'select',
            'list' => $groupsList,
            'filter_key' => 'a!id_default_group' //Clé de filtrage dans la requête sous la forme "NomTable!champ" 
            )
        );
        $this->addNewFieldAfter($newField, 'lastname', $params['fields']);
    }
 
	 /**
     * Ajout du nouveau champ après
     * @param type $fieldParams
     * @param type $afertName
     * @param type $fieldsArray
     */
    public function addNewFieldAfter($fieldParams,$afterName,array &$fieldsArray)
    {
 
        if (array_key_exists($afterName, $fieldsArray)) {
            $pos = array_search($afterName, array_keys($fieldsArray));
            $before = array_slice($fieldsArray,0,$pos+1);
            $after = array_slice($fieldsArray, $pos); 
            $fieldsArray = array_merge($before,$fieldParams,$after);
 
        } else {
            $fieldsArray = array_merge($fieldsArray,$fieldParams);
        }
    }
}

22 réflexions sur “Prestashop : Modifier les listings dans l’administration”

  1. Bonjour,
    Merci de l’info, pour un presta 1.6, on a une erreur quand on fait une recherche par filtre :

    [8] Undefined index: select
    [8] Undefined index: join

  2. Salut,

    De mon côté, j’utilise ce code pour afficher le moyen de transport, je vois pas comment utiliser ton code pour changer de place a cette nouvelle colonne, si tu peux m’aider, merci d’avance!
    $this->_join .= ‘ LEFT JOIN `’._DB_PREFIX_.’carrier` crr ON (crr.`id_carrier` = a.`id_carrier`)’;

    $this->_select = ‘crr.`name` AS `carrier_name`,’.$this->_select;

    $this->fields_list[‘carrier_name’] = array(

    ‘title’ => $this->l(‘Transport ‘),

    ‘width’ => 100,

    ‘havingFilter’ => true,

    );

    1. Bonjour Vincent,
      Le code que tu montre ne semble pas issu d’un module, car le code utilisé utilise la variable $this->
      Je suppose que tu édites directement un controller admin ?
      Attention sur les dernières versions de la 1.7 il y’a de plus en plus de controlleurs qui utilisent la nouvelle infrastructure ou ce tutoriel n’est plus valide.

      Cordialement,
      Hervé

    1. Dans ce cas il faut rajouter la fonction addNewFieldAfter dans cette classe.
      Déclarer ton champ dans une variable à part :
      $newField = array( 'default_group_name' =>
      array(
      'title' => $this->l('Groupe par défaut'),
      ...
      );

      et le seul point à changer est de passer $this->fields_list à la place de $params[‘fields’] normalement cela devrait fonctionner.

      Cordialement,

  3. Ca n’as pas l’ai de fonctionner, j’obtiens une page erreur 500.
    Voila le code adapté

    $this->_join .= ‘ LEFT JOIN `’._DB_PREFIX_.’carrier` crr ON (crr.`id_carrier` = a.`id_carrier`)’;

    $this->_select = ‘crr.`name` AS `carrier_name`,’.$this->_select;

    $newField = array( ‘carrier_name’ =>
    array(
    ‘title’ => $this->l(‘Transport ‘),

    ‘width’ => 100,

    ‘havingFilter’ => true,
    )
    );

    $this->addNewFieldAfter($newField, ‘company’, $params[‘fields’]);

    public function addNewFieldAfter($fieldParams,$afterName,array &$fieldsArray)
    {

    if (array_key_exists($afterName, $fieldsArray)) {
    $pos = array_search($afterName, array_keys($fieldsArray));
    $before = array_slice($fieldsArray,0,$pos+1);
    $after = array_slice($fieldsArray, $pos);
    $fieldsArray = array_merge($before,$fieldParams,$after);

    } else {
    $fieldsArray = array_merge($fieldsArray,$fieldParams);
    }
    }

  4. vincent@seofever.fr

    Voila l’erreur:
    Catchable fatal error: Argument 3 passed to AdminOrdersController::addNewFieldAfter() must be of the type array, null given, called in /home/batteriexm/www/override/controllers/admin/AdminOrdersController.php on line 34 and defined

    Voila la ligne 34:
    ‘title’ => $this->l(‘Transport ‘),

    Merci

    1. Bonjour,
      L’erreur est claire, l’élément que vous passez en 3ème paramètre lors de l’appel à la fonction addNewFieldAfter est null.
      Alors qu’un tableau est requis. , la ligne 34 ne colle pas du tout avec l’erreur par contre.

  5. A ce niveau là
    $this->addNewFieldAfter($newField, ‘company’, $params[‘fields’]);

    Ou dans la fonction?

    public function addNewFieldAfter($fieldParams,$afterName,array &$fieldsArray)
    {

    if (array_key_exists($afterName, $fieldsArray)) {
    $pos = array_search($afterName, array_keys($fieldsArray));
    $before = array_slice($fieldsArray,0,$pos+1);
    $after = array_slice($fieldsArray, $pos);
    $fieldsArray = array_merge($before,$fieldParams,$after);

    } else {
    $fieldsArray = array_merge($fieldsArray,$fieldParams);
    }
    }

    1. Dans l’appel de la fonction, $params[‘fields’] n’est pas défini dans votre cas puisque vous êtes dans un controller admin.
      Comme déjà remonté dans mon précédent commentaire, le 3ème paramètre à renvoyer est $this->fields_list 😉

  6. marianne.sett@gmail.com

    Bonjour;

    je suis débutante et je n’arrive pas à faire marcher votre code.
    le module ne s’affiche pas du tout. j’ai vidé le cache etc…

    pourriez vous détailler un peu plus les étapes s’il vous plait? ^^’

    Cordialement

    1. Bonjour,

      Désolé mais je peux difficilement détailler plus le processus.

      Par ailleurs vous ne précisez pas sur quelle version vous testez le module ?

      Si c’est sur une version supérieure ou égale à la 1.7.6 cela ne fonctionnera effectivement plus car ce controller a été migré vers la nouvelle architecture symfony.

      Cordialement,
      Hervé

  7. Bonjour,

    je suis en version 1.7.4.2 .

    Je dois mettre ce code ou exactement? J’ai crée un dossier que j’ai nommé hh_admin dans lequel j’ai crée un fichier ou j’ai collé le code complet que vous donnez en le nommant AdminController.php . ça n’a pas fonctionné.
    j’ai essayé autre chose en le plaçant dans un dossier override/classes .

    IL ne se passe rien.

    Je me doutes bien que ce n’est pas la bonne façon de faire. Mais il n’y a pas plus d’instructions sur comment le faire concrètement. ^^’

    Je vous remercie par avance de votre aide.

    Cordialement

    1. Bonjour,

      Effectivement suite à votre dernier message je constate qu’il vous manque les bases de la programmation Prestashop.

      Ce blog est de manière générale, adressé à un public assez technique c’est pour cela que je ne détaille pas (plus) les étapes basiques.
      N’hésitez pas à consulter la documentation officielle pour mieux appréhender la solution : https://devdocs.prestashop.com/1.7/modules/introduction/

      Pour faire marcher mon code il sera nécessaire de créer un dossier hhadmin dans le dossier modules et de mettre le contenu dans un fichier hhadmin.php
      Il faudra ensuite installer ce module via l’administration.
      Attention toutefois car ce module n’est qu’un POC ( proof of concept ) qui explique le fonctionnement technique de l’ajout d’informations.

      Cordialement,
      Hervé

  8. Bonjour,
    je ne suis pas un expert dans le dev prestashop, j’ai essayé d’intégrer votre module à mon prestashop 1.6.1. Seulement je n’observe aucun changement.
    J’ai ajouter à www/classes/controller/adminController.php getList() le hook dynamique que vous évoquez au debut du tutoriel et dans www/modules/hhadmin/hhadmin.php votre premiers script php donné.
    Le module est bien présent et activer sur mon prestashop. Seulement je ne vois le title et le optin unset comme vous.
    Est ce que j’aurai mal fait ou sauté une étape ?
    Merci à vous par avance
    Alexandre

    1. Bonjour,
      Est-ce que vous voulez dire en version 1.7.6.1 de prestashop ?
      Si c’est le cas les clients utilisent maintenant la nouvelle infrastructure et ce tutoriel n’est effectivement plus valide.

      Cordialement,
      Hervé

Laisser un commentaire

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