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); } } } |
janvier 31st, 2019
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
janvier 31st, 2019
Bonjour Jonathan,
Sur quelle version exacte de prestashop 1.6 ?
Quelle est la modification que vous souhaitez faire ?
Cordialement,
Hervé
juin 27th, 2019
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,
);
juin 28th, 2019
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é
juin 28th, 2019
Bonjour Hervé,
Merci pour ta réponse.
Je suis sous Prestashop 1.6.1.6
Mon code est un override de AdminOrdersController.php
juin 28th, 2019
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,
juin 29th, 2019
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);
}
}
juillet 1st, 2019
Quel est le message renvoyé par l’erreur 500 ?
(Il faut être en mode debug pour le visualiser 😉 )
juillet 1st, 2019
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
juillet 1st, 2019
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.
juillet 1st, 2019
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);
}
}
juillet 1st, 2019
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 😉
juillet 1st, 2019
Exact, merci!
octobre 29th, 2019
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
octobre 29th, 2019
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é
octobre 30th, 2019
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
octobre 30th, 2019
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é
décembre 3rd, 2019
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
décembre 3rd, 2019
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é
décembre 3rd, 2019
Merci de votre retour, non je veux dire la version 1.6.1.20
janvier 8th, 2021
Bonjour Hervé,
Une idée pour adapter ce module à l’architecture Symphony de la 1.7.6 ?
Bien cordialement.
Renaud
janvier 9th, 2021
Bonjour Renaud,
Sur la version 1.7.6 il y’a un exemple sur la documentation officielle 🙂 ( qui est de plus en plus complète 🙂 )
https://devdocs.prestashop.com/1.7/modules/sample-modules/grid-and-identifiable-object-form-hooks-usage/
Cordialement,
Hervé