{"id":1654,"date":"2017-11-15T22:25:45","date_gmt":"2017-11-15T20:25:45","guid":{"rendered":"https:\/\/www.h-hennes.fr\/blog\/?p=1654"},"modified":"2023-09-13T08:13:42","modified_gmt":"2023-09-13T06:13:42","slug":"prestashop-1-7-ajouter-des-champs-dans-le-listing-produit-admin","status":"publish","type":"post","link":"https:\/\/www.h-hennes.fr\/blog\/2017\/11\/15\/prestashop-1-7-ajouter-des-champs-dans-le-listing-produit-admin\/","title":{"rendered":"Prestashop 1.7 : Ajouter des champs dans le listing produit admin"},"content":{"rendered":"<p>A la suite de mon pr\u00e9c\u00e9dent article sur comment ajouter des champs produits dans l&rsquo;administration de prestashop 1.7 : <a href=\"https:\/\/www.h-hennes.fr\/blog\/2017\/10\/19\/prestashop-1-7-ajouter-des-champs-produit\/\">https:\/\/www.h-hennes.fr\/blog\/2017\/10\/19\/prestashop-1-7-ajouter-des-champs-produit\/<\/a> , nous allons \u00e0 pr\u00e9sent voir comment ajouter des champs dans le listing des produits de l&rsquo;administration.<\/p>\n<p>Cette page est g\u00e9r\u00e9e via les nouveaux controllers symfony et leur fonctionnement est donc diff\u00e9rents des autres listing de l&rsquo;administration.<\/p>\n<p>&nbsp;<\/p>\n<p>Je ne d\u00e9taille pas la base de la cr\u00e9ation du module qui pourra reprendre celle de l&rsquo;article sur la cr\u00e9ation des champs produits.<\/p>\n<p>Le module devra impl\u00e9menter les hooks suivants :<\/p>\n<ul>\n<li>actionAdminProductsListingFieldsModifier (hook natif )<\/li>\n<li>displayAdminCatalogTwigListingProductFields ( hook custom)<\/li>\n<li>displayAdminCatalogTwigProductFilter ( hook custom )<\/li>\n<li>displayAdminCatalogTwigProductHeader ( hook custom )<\/li>\n<\/ul>\n<p>Pour l&rsquo;exemple nous allons ajouter un filtre sur les marques des produits, mais la logique s&rsquo;applique \u00e0 n&rsquo;importe quel champ.<\/p>\n<p><strong>Modification des fichiers twigs pour la cr\u00e9ation des nouveaux hooks<\/strong><\/p>\n<p><strong>Prestashop 1.7.2.x et inf\u00e9rieurs :<\/strong><\/p>\n<p>Avec les versions <strong>1.7.2.x et inf\u00e9rieures<\/strong> il n&rsquo;est pas possible de r\u00e9aliser cette modification sans toucher \u00e0 des fichiers \u00ab\u00a0coeur\u00a0\u00bb puisque la surcharge des templates symfony n&rsquo;est pas encore g\u00e9r\u00e9e via les modules.<\/p>\n<p>Pour autant la solution que je propose reste assez propre les seules lignes qui seront ajout\u00e9es le seront pour ajouter un appel de hook.<\/p>\n<p>Les templates utilis\u00e9s pour le listing des produits seront donc les suivants :<\/p>\n<ul>\n<li>src\\PrestaShopBundle\\Resources\\views\\Admin\\Product\\catalog.html.twig<\/li>\n<li>src\\PrestaShopBundle\\Resources\\views\\Admin\\Product\\list.html.twig<\/li>\n<\/ul>\n<p><strong>Prestashop 1.7.3.x et sup\u00e9rieur :<\/strong><\/p>\n<p>A partir de cette version il est possible de surcharger facilement les templates depuis votre module.<br \/>\nVous pouvez trouver la source de l&rsquo;information\u00a0 sur le gist de Mick\u00e4el Andrieu : https:\/\/gist.github.com\/mickaelandrieu\/4a02ea05bb1113718aec5432ad418ee5<br \/>\nDans notre cas il faut cr\u00e9er les fichiers de templates suivant dans le module<\/p>\n<ul>\n<li>views\/PrestaShop\/Admin\/Product\/catalog.html.twig<\/li>\n<li>views\/PrestaShop\/Admin\/Product\/list.html.twig<\/li>\n<\/ul>\n<p>Vous pouvez reprendre l&rsquo;int\u00e9gralit\u00e9 du contenu des fichiers sources\u00a0 et y appliquer les m\u00eames modifications.<\/p>\n<p>Dans <em>catalog.html.twig<\/em> :<\/p>\n<p>Rajouter le code suivant :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> {# Hhennes Hook Custom pour afficher des colonnes suppl\u00e9mentaires #}\r\n {{ renderhook('displayAdminCatalogTwigProductHeader') }}\r\n<\/pre>\n<p>Apr\u00e8s le code :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> &lt;th&gt;\r\n {{ \"Category\"|trans({}, 'Admin.Catalog.Feature') }}\r\n {% include 'PrestaShopBundle:Admin\/Product\/Include:catalog_order_carrets.html.twig' with {\r\n 'column': 'name_category'\r\n } %}\r\n &lt;\/th&gt;\r\n<\/pre>\n<p>Rajouter le code suivant :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> {# Hhennes Hook Custom pour afficher des filtres suppl\u00e9mentaires #}\r\n {{ renderhook('displayAdminCatalogTwigProductFilter') }}\r\n<\/pre>\n<p>Apr\u00e8s le code :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> &lt;th&gt;\r\n &lt;input\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"{{ \"Search category\"|trans({}, 'Admin.Catalog.Help') }}\"\r\n name=\"filter_column_name_category\"\r\n value=\"{{ filter_column_name_category }}\"\r\n \/&gt;\r\n &lt;\/th&gt;<\/pre>\n<p>Dans <em>list.html.twig<\/em> :<br \/>\nRajouter le code suivant :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> {# Hhennes Hook Custom pour afficher les nouveaux champs dans le listing #}\r\n {{ renderhook('displayAdminCatalogTwigListingProductFields', { 'product': product }) }}\r\n<\/pre>\n<p>Apr\u00e8s le code :<\/p>\n<pre lang=\"twig\" escaped=\"true\"> &lt;td&gt;\r\n {{ product.name_category|default('') }} \r\n &lt;\/td&gt;\r\n<\/pre>\n<p><strong>Affichage des nouveaux champs via les hooks du fichier twig<\/strong><\/p>\n<p>Nos nouveaux hooks \u00e9tant maintenant cr\u00e9\u00e9 il est temps d&rsquo;ajouter nos champs via les hooks du module :<\/p>\n<p>hook <span style=\"text-decoration: underline;\">displayAdminCatalogTwigProductHeader<\/span> : Affichage de l&rsquo;ent\u00eate de la colonne<\/p>\n<pre lang=\"php\" escaped=\"true\"> \/**\r\n * Hook personnalis\u00e9 ( non core ) pour afficher le header product\r\n * cf. src\\PrestaShopBundle\\Resources\\views\\Admin\\Product\\catalog.html.twig\r\n * @param type $params\r\n *\/\r\n public function hookDisplayAdminCatalogTwigProductHeader($params)\r\n {\r\n return $this-&gt;display(__FILE__,'views\/templates\/hook\/displayAdminCatalogTwigProductHeader.tpl'); \r\n }\r\n<\/pre>\n<p>Contenu du fichier <em>displayAdminCatalogTwigProductHeader.tpl<\/em> :<\/p>\n<pre lang=\"smarty\" escaped=\"true\"> &lt;th&gt;{l s='Manufacturer' mod='hhproduct'}&lt;\/th&gt;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>hook <span style=\"text-decoration: underline;\">displayAdminCatalogTwigProductFilter<\/span> : Affichage du champ html du filtre<\/p>\n<pre lang=\"php\" escaped=\"true\"> \/**\r\n * Hook personnalis\u00e9 ( non core ) pour afficher le filter product\r\n * cf. src\\PrestaShopBundle\\Resources\\views\\Admin\\Product\\catalog.html.twig\r\n * @param type $param\r\n *\/\r\n public function hookDisplayAdminCatalogTwigProductFilter($params)\r\n {\r\n $manufacturers = Manufacturer::getManufacturers();\r\n $this-&gt;context-&gt;smarty-&gt;assign(\r\n [\r\n 'filter_column_name_manufacturer' =&gt; Tools::getValue('filter_column_name_manufacturer',''),\r\n 'manufacturers' =&gt; $manufacturers,\r\n ]\r\n );\r\n return $this-&gt;display(__FILE__,'views\/templates\/hook\/displayAdminCatalogTwigProductFilter.tpl');\r\n }\r\n<\/pre>\n<p>Contenu du fichier <em>displayAdminCatalogTwigProductFilter.tpl<\/em> :<\/p>\n<pre lang=\"smarty\" escaped=\"true\"> &lt;th&gt;\r\n &lt;select name=\"filter_column_name_manufacturer\" data-toggle=\"select2\"&gt;\r\n &lt;option value=\"\"&gt;{l s='Manufacturer' mod='hhproduct'}&lt;\/option&gt;\r\n {foreach from=$manufacturers item=manufacturer}\r\n &lt;option value=\"{$manufacturer.id_manufacturer}\" \r\n {if $filter_column_name_manufacturer == $manufacturer.id_manufacturer} selected=\"selected\"{\/if}&gt;\r\n {$manufacturer.name}\r\n &lt;\/option&gt;\r\n {\/foreach}\r\n &lt;\/select&gt;\r\n&lt;\/th&gt;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>hook <span style=\"text-decoration: underline;\">displayAdminCatalogTwigListingProductFields<\/span> : Affichage de la valeur du champ pour chaque produit<\/p>\n<pre lang=\"php\" escaped=\"true\"> \/**\r\n * Hook personnalis\u00e9 (non core) pour afficher les informations additionnelles produits )\r\n * cf. src\\PrestaShopBundle\\Resources\\views\\Admin\\Product\\list.html.twig\r\n * @param type $params\r\n *\/\r\n public function hookDisplayAdminCatalogTwigListingProductFields($params)\r\n {\r\n $this-&gt;context-&gt;smarty-&gt;assign('product',$params['product']);\r\n return $this-&gt;display(__FILE__,'views\/templates\/hook\/displayAdminCatalogTwigListingProductFields.tpl');\r\n }\r\n<\/pre>\n<p>Contenu du fichier <em>displayAdminCatalogTwigListingProductFields.tpl<\/em> :<\/p>\n<pre lang=\"smarty\" escaped=\"true\"> &lt;td&gt;{$product.manufacturer}&lt;\/td&gt;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Avec ces codes nous devrions \u00e0 pr\u00e9sent obtenir l&rsquo;affichage suivant :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1655\" src=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer.jpg\" alt=\"Prestashop produt fields\" width=\"780\" height=\"209\" srcset=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer.jpg 780w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-300x80.jpg 300w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-768x206.jpg 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>C&rsquo;est bien joli mais il n&rsquo;y a pas de donn\u00e9es \ud83d\ude09<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Affichage et filtrage des r\u00e9sultats<\/strong><\/p>\n<p>Pour remonter ces donn\u00e9es la bonne nouvelle c&rsquo;est que le hooks natif de prestashop 1.6 fonctionne encore !<br \/>\nDans le fichier <em>\\src\\Adapter\\Product\\AdminProductDataProvider.php<\/em>, le hook <strong>actionAdminProductsListingFieldsModifier<\/strong> est toujours appell\u00e9.<br \/>\nComme vous pouvez le voir ligne 280<\/p>\n<pre lang=\"php\" escaped=\"true\"> \/\/ exec legacy hook but with different parameters (retro-compat &lt; 1.7 is broken here)\r\n \\HookCore::exec('actionAdminProductsListingFieldsModifier', array(\r\n '_ps_version' =&gt; _PS_VERSION_,\r\n 'sql_select' =&gt; &amp;$sqlSelect,\r\n 'sql_table' =&gt; &amp;$sqlTable,\r\n 'sql_where' =&gt; &amp;$sqlWhere,\r\n 'sql_order' =&gt; &amp;$sqlOrder,\r\n 'sql_limit' =&gt; &amp;$sqlLimit,\r\n ));\r\n<\/pre>\n<p>Voici donc l&rsquo;impl\u00e9mentation du hook dans notre module :<\/p>\n<pre lang=\"php\" escaped=\"true\">\/**\r\n* Modification de la requ\u00eate de la liste\r\n* @param type $params\r\n*\/\r\npublic function hookActionAdminProductsListingFieldsModifier($params)\r\n{\r\n\/**\r\n* Rajout du fabricant\r\n*\/\r\n\/\/Champ sql\r\n$params['sql_select']['manufacturer'] = [\r\n'table' =&gt; 'm',\r\n'field' =&gt; 'name',\r\n'filtering' =&gt; \\PrestaShop\\PrestaShop\\Adapter\\Admin\\AbstractAdminQueryBuilder::FILTERING_LIKE_BOTH\r\n];\r\n\/\/Table sql\r\n$params['sql_table']['m'] = [\r\n'table' =&gt; 'manufacturer',\r\n'join' =&gt; 'LEFT JOIN',\r\n'on' =&gt; 'p.`id_manufacturer` = m.`id_manufacturer`',\r\n];\r\n\r\n\/\/Gestion du filtre, si un param\u00e8tre post est d\u00e9fini ( c'est le nom du champ dans le fichier displayAdminCatalogTwigProductFilter.tpl )\r\n$manufacturer_filter = Tools::getValue('filter_column_name_manufacturer',false);\r\nif ( $manufacturer_filter &amp;&amp; $manufacturer_filter != '') {\r\n$params['sql_where'][] .= \"p.id_manufacturer =\".$manufacturer_filter;\r\n}\r\n}\r\n<\/pre>\n<p>Voici donc comment rajouter et filtrer les r\u00e9sultats de l&rsquo;attribut manufacturer \ud83d\ude42<\/p>\n<p>Et voici le rendu final, avec le filtre qui fonctionne :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1656\" src=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-ok.jpg\" alt=\"Colonne manufacturer OK\" width=\"780\" height=\"208\" srcset=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-ok.jpg 780w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-ok-300x80.jpg 300w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2017\/11\/column-manufacturer-ok-768x205.jpg 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><strong>EDIT 2018-03-20 : Ajout des informations pour PS 1.7.3 et sup\u00e9rieur<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A la suite de mon pr\u00e9c\u00e9dent article sur comment ajouter des champs produits dans l&rsquo;administration de prestashop 1.7 : https:\/\/www.h-hennes.fr\/blog\/2017\/10\/19\/prestashop-1-7-ajouter-des-champs-produit\/ , nous allons \u00e0 pr\u00e9sent voir comment ajouter des champs dans le listing des produits de l&rsquo;administration. Cette page est g\u00e9r\u00e9e via les nouveaux controllers symfony et leur fonctionnement est donc diff\u00e9rents des autres listing [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[245],"tags":[348,507,483],"class_list":["post-1654","post","type-post","status-publish","format-standard","hentry","category-prestashop-2","tag-admin","tag-listing-produit","tag-prestashop-1-7","prestashop-1-6","prestashop-1-7","prestashop-1-7-2","prestashop-1-7-3","prestashop-1-7-4","prestashop-1-7-5","prestashop-1-7-6","prestashop-1-7-7","prestashop-1-7-8","prestashop-8-0","prestashop-8-1"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1654","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/comments?post=1654"}],"version-history":[{"count":6,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1654\/revisions"}],"predecessor-version":[{"id":2325,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1654\/revisions\/2325"}],"wp:attachment":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/media?parent=1654"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/categories?post=1654"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/tags?post=1654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}