Jump to content

Enlever les doublons dans product-list avec SELECT DISTINCT. Comment faire ?


Recommended Posts

Bonjour,

Je recherche activement une solution à mon problème.

J'ai plusieurs articles qui sont similaires, avec le même EAN. Actuellement avec une recherche par catégories ou par mots clés, tous les produits apparaissent dans la liste de résultat, ce qui peut être rébarbatif de tomber sur les mêmes produits, et donnant l'impression d'un manque d'organisation.

Ce que je voudrais :
C'est qu'un seul produit apparaisse (un peu comme une fiche générale regroupant tous les produits identiques) à la recherche du mot clé ou par navigation de catégories. Lorsque l'on cliquerait sur cette fiche, les produits identiques uniquement apparaitraient (même format que la liste de produit actuelle) avec les divers variantes indiquées comme l'état, le prix, l'édition, la photo, la référence... Puis ensuite lorsque l'on cliquerait sur un des produits, cela afficherait la page classique du produit [product.tpl]. L'idéal serait ensuite lors d'un import .csv de pouvoir mettre automatiquement le produit dans la fiche générale à l'aide de l'EAN ou de l'ID de la fiche générale.

Au final il y aurait donc une page à insérer entre le product-list et le product.

Je ne sais pas trop si il faut créer une autre page, modifier celle du product-list, du product, faire apparait la fiche générale comme une catégorie, ...

Auriez vous une piste ?
Je suis également prêt à rémunérer toute personne qui prendrait en charge mon problème pour m'apporter la solution sur un plateau ;)

Version PS : 1.2.5

Merci :)

Link to comment
Share on other sites

Bonjour,

Ce sont des produits culturels genre livres, cd,...

Si tu prends par exemple le livre :

"Le malade imaginaire"

Je vais avoir différentes éditions, parfois neuf, parfois d'occasion, dont certains avec le meme EAN (mais pas tous), mais ce seront des références internes différentes et à des prix différents alors qu'en fait c'est le même livre.
Je peux également avoir certains articles concernés n'ayant pas d'EAN, mais que je souhaiterais regrouper aussi en une seule fiche.
Si tu recherches le mot clé "malade imaginaire", il faudrait tomber sur cette unique fiche (comme une liste de produits classiques par défaut sur prestashop), pour cliquer dessus, et ensuite voir les différents modèles proposés (comme une liste de produits classiques par défaut sur prestashop).

Link to comment
Share on other sites

Personne n'a d'idée sur une solution plausible ?


- modifier "product.tpl" de façon à faire apparaitre les autres articles ?

- créer une page entre "product-list" et "product" ?

- afficher les catégories dans la colonne centrale et créer une catégorie par fiche produit ? Mais dans ce cas, peut on rechercher une "catégorie" par mots clés, et peut-on empêcher d'afficher plusieurs résultats en cas de recherche de mots (le but étant de faire apparaitre uniquement une fiche, puis tous les articles en cliquant dessus, et non d'afficher tous les articles directement) ?

- modifier "product-list" de façon à n'afficher qu'un résultat (le moins cher par exemple), avec un petit lien "afficher les autres articles disponibles" qui ferait dérouler en dessous de l'annonce les autres choix ?

Link to comment
Share on other sites

  • 3 weeks later...

J'ai pas de piste mais juste une question (car non abordé) : Pourquoi ne pas utiliser les déclinaisons ?

Les déclinaisons te permette de faire plusieurs versions d'un même produit (avec photo différente et tout) avec prix, poids et référence différentes.

Link to comment
Share on other sites

Bonjour,

J'avais jeté un oeil sur les déclinaisons par la suite. Seulement je souhaiterais que chaque produit ait le même espace dans lequel figurerait la photo de l'article, la description, la référence, le prix, l'état, le bouton "ajouter au panier".
Si j'utilise les déclinaisons, il n'y a qu'un seul encadrement où les déclinaisons s'affichent dans un menu déroulant (sauf erreur de ma part).

Link to comment
Share on other sites

La solution serait probablement de modifier product-list.php pour afficher les produits groupés par code EAN (comme ça, pas de "faux doublons"), ensuite, cette même page évalue dans sa boucle d'affichage de produit si le produit à des "frères d'EAN".

Si c'est le cas, on va sur une page que l'on nommera group-product.php?ean=1234567890, sinon, directement sur la fiche produit : product.php?id_product=123 (Bon, tout cela est faisable avec l'url rewriting aussi si besoin).

Ce fichier groupe-product.php serait presque similaire à product-list.php sauf qu'il s'agit là de regrouper des codes EAN et non des catégories.

Pour résumer, à modifier :

/product-list.php
/themes/mon_themes/product-list.tpl

A ajouter :

/group-list.php
/group-list.tpl

En tout cas, c'est l'algo que j'utiliserais. Tout le reste c'est de la requête SQL et un peu de PHP. J'espère t'avoir apporté un début de réponse.

Link to comment
Share on other sites

Très bien, j'ai compris le raisonnement, c'est déja un bon début.
Il y a cependant un couac, je ne trouve pas de fichier "product-list.php" sous htdocs. Peut être est il placé à un endroit où je ne l'ai pas vu.
Je ne vois que "product.php" et "product-sort.php". Faudrait il voir du coté de category.php ?

Link to comment
Share on other sites

Désolé, je suis allé un peu rapidement, c'est category.php en fait.

En y regardant bien, le code qui est vraiment utilisé par product-list.tpl est vraiment cours dans ce fichier :

            $nbProducts = $category->getProducts(NULL, NULL, NULL, $orderBy, $orderWay, true);
           include(dirname(__FILE__).'/pagination.php');
           $smarty->assign('nb_products', $nbProducts);
           $cat_products = $category->getProducts(intval($cookie->id_lang), intval($p), intval($n), $orderBy, $orderWay);



Le plus intéressant, c'est que si tu arrive à faire une méthode dans la classe "Category" genre "getProductsroupedByEAN" qui ressemble à "getProducts", alors tu aura bien avancé car il n'y a que deux getProducts sur cette page.

Link to comment
Share on other sites

J'ai regardé classes/category.php , là par contre c'est une autre paire de manche pour déchiffrer tout ça. J'arrive à modifier certaines informations en testant en simultané, par contre la manipulation / création des fonctions, je n'y arrive pas (au passage si quelqu'un connait un bon site en français qui pourrait m'aider à y voir plus clair ...). Cependant j'ai vraiment l'envie de comprendre, ce qui serait déjà un plus indéniable si je sais d'avance où je dois mettre les pieds.

Bon je fais un résumé, de ce que j'ai compris.

Dans product-list.tpl :
Je modifie de façon à ce que ce soit group-list.tpl qui soit appelé et non product.tpl

Dans group-list.tpl :
Je crée en utilisant le fichier product-list.tpl comme base. Quels seraient les modifications à faire ?

Dans category.php :
Je dois modifier/ajouter le code de façon à ce que la page n'affiche pas de doublons lors d'une recherche par catégorie (par mot clé aussi ?)

Dans classes/category.php :
Là je suis perdu ! Je ne comprend pas trop ce qu'il faudrait faire ici.

Dans group-list.php :
Je prend category.php comme modèle, et dois mettre un code da façon à ce que la page n'affiche que les articles ayant le même EAN. Cela suppose t-il qu'il faut donc supprimer une partie du fichier ?



Y-aurait il des autres fichiers où il y aurait une intervention à faire ? Par exemple, ne risque t-il pas d'y avoir des bugs dans la page product-list par rapport à l'affichage des données des produits si il y en a plusieurs (prix ne correspondant pas à l'état ne correspondant lui même pas au bon article,...) ?

Link to comment
Share on other sites

Il y a juste une étape que tu as sauté, c'est que si le produit sur lequel on clique n'a pas de "frère EAN" alors on arrive durectement sur product.tpl.

group-list.tpl est pratiquement identique à product-list.tpl, je dirait même exactement pareil, ce qui change vraiment, c'est group-list.php

category.php : Il faut changer la méthode getProducts par getProductsGroupByEAN et créer cette méthode dans la classe Category juste pour changer la façon dont la page charge les produits.

Classe Catégorie : Cette classe permet, entre autre, grâce à la fonction getProducts, d'avoir tous les produits d'une catégorie que Smarty va assigner dans l'ancien product-list.tpl. En créant getProductsGroupByEAN, tu peut faire en sorte que les produits de s'affichent pas en doublon (Avec un "GROUP BY ean" par exemple, attention, je ne connais pas pas le nom de ce champ).
Et il faut créer aussi une nouvelle méthode getProductByEAN où on affiche seulement les produits ayant le même code EAN et sera utilisé dans group-list.php.

Il n'y a pas d'intervention dans les fichiers si tout est fait.

Link to comment
Share on other sites

Quelle est la délimitation de la zone où il faut faire la modification dans classes/category.php ? Je repère bien la fonction GetProducts, mais je n'arrive pas à la décrypter ni à la délimiter.


public function getProducts($id_lang, $p, $n, $orderBy = NULL, $orderWay = NULL, $getTotal = false, $active = true, $random = false, $randomNumberProducts = 1)
   {
       global $cookie;

       if ($p < 1) $p = 1;
       if (empty($orderBy))
           $orderBy = 'position';
       if (empty($orderWay))
           $orderWay = 'ASC';
       if ($orderBy == 'id_product' OR    $orderBy == 'date_add')
           $orderByPrefix = 'p';
       elseif ($orderBy == 'name')
           $orderByPrefix = 'pl';
       elseif ($orderBy == 'manufacturer')
       {
           $orderByPrefix = 'm';
           $orderBy = 'name';
       }
       elseif ($orderBy == 'position')
           $orderByPrefix = 'cp';

       if ($orderBy == 'price')
           $orderBy = 'orderprice';

       if (!Validate::isBool($active) OR !Validate::isOrderBy($orderBy) OR !Validate::isOrderWay($orderWay))
           die (Tools::displayError());

       $id_supplier = intval(Tools::getValue('id_supplier'));

       /* Return only the number of products */
       if ($getTotal)
       {
           $result = Db::getInstance()->getRow('
           SELECT COUNT(cp.`id_product`) AS total
           FROM `'._DB_PREFIX_.'product` p
           LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`
           WHERE cp.`id_category` = '.intval($this->id).($active ? ' AND p.`active` = 1' : '').'
           '.($id_supplier ? 'AND p.id_supplier = '.$id_supplier : '').'');
           return isset($result) ? $result['total'] : 0;
       }

       $sql = '
       SELECT p.*, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, cl.`name` AS category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new,
                   (p.price - IF((DATEDIFF(reduction_from, CURDATE()) <= 0 AND DATEDIFF(reduction_to, CURDATE()) >=0) OR reduction_from = reduction_to, IFNULL(reduction_price, (p.price * reduction_percent / 100)),0)) AS orderprice 
       FROM `'._DB_PREFIX_.'category_product` cp
       LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
       LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product` AND default_on = 1)
       LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
       LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'tax` t ON t.`id_tax` = p.`id_tax`
       LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
       WHERE cp.`id_category` = '.intval($this->id).($active ? ' AND p.`active` = 1' : '').'
       '.($id_supplier ? 'AND p.id_supplier = '.$id_supplier : '');

       if ($random === true)
       {
           $sql .= 'ORDER BY RAND()';
           $sql .= 'LIMIT 0, '.intval($randomNumberProducts);
       }
       else
       {
           $sql .= 'ORDER BY '.(isset($orderByPrefix) ? $orderByPrefix.'.' : '').'`'.pSQL($orderBy).'` '.pSQL($orderWay).'
           LIMIT '.((intval($p) - 1) * intval($n)).','.intval($n);
       }

       $result = Db::getInstance()->ExecuteS($sql);

       if ($orderBy == 'orderprice')
       {
           Tools::orderbyPrice($result, $orderWay);
       }
       if (!$result)
           return false;

Link to comment
Share on other sites

Il faut créer une méthode similaire à celle ci mais en changeant les requetes SQL soit

$result = Db::getInstance()->getRow('
           SELECT COUNT(cp.`id_product`) AS total
           FROM `'._DB_PREFIX_.'product` p
           LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`
           WHERE cp.`id_category` = '.intval($this->id).($active ? ' AND p.`active` = 1' : '').'
           '.($id_supplier ? 'AND p.id_supplier = '.$id_supplier : '').'');



et

$sql = '
       SELECT p.*, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, cl.`name` AS category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new,
                   (p.price - IF((DATEDIFF(reduction_from, CURDATE()) <= 0 AND DATEDIFF(reduction_to, CURDATE()) >=0) OR reduction_from = reduction_to, IFNULL(reduction_price, (p.price * reduction_percent / 100)),0)) AS orderprice 
       FROM `'._DB_PREFIX_.'category_product` cp
       LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
       LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product` AND default_on = 1)
       LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
       LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'tax` t ON t.`id_tax` = p.`id_tax`
       LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.intval($id_lang).')
       LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
       WHERE cp.`id_category` = '.intval($this->id).($active ? ' AND p.`active` = 1' : '').'
       '.($id_supplier ? 'AND p.id_supplier = '.$id_supplier : '');



de façon à virer les doublons sur les EAN

Link to comment
Share on other sites

  • 4 weeks later...

Bon alors voici où j'en suis.
J'ai fait beaucoup de recherches pour voir des situations similaires. Apparemment il faut modifier les fichiers classes sans toucher aux fichiers php sous htdocs.

J'arrive à faire la requête SQL sur Phpmyadmin pour avoir la liste totale des articles à afficher sans aucun doublons, mais je n'arrive pas à l'intégrer dans le fichier classes/Search.php

$sql ='( SELECT DISTINCT ean13 FROM ps_product ) UNION ( SELECT DISTINCT name FROM ps_product_lang ) LIMIT 0, 30 ';

Je souhaiterais donc intégrer cette requête au bon endroit (créer et/ou modifier?) dans mes fichiers Search.php et Category.php (je pense que ce sont les 2 uniques fichiers concernés, corrigez moi si je me trompe), en sachant que la recherche par mot clé doit se faire avec le résultat $sql ci dessus, et non parmi tous mes articles en ligne.
Je joins Search.php si ça peut aider.
Merci de votre aide.

Search.php

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...