Jump to content

[RESOLU] afficher tous les produits en excluant une catégorie


Recommended Posts

Bonjour,

 

Je cherche à exclure une categorie mais je ne sais pas si j'utilise la bonne methode, je m'explique:

 

avec cette méthode

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, true);

j'affiche tous les produits actifs de toutes les catégories.

 

en modifiant l'avant dernier parametre

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', 2, true);

Je n'affiche que les produits de la categorie dont l'id est 2

 

mais comment puis-je afficher tous les produits sauf ceux de la categorie dont l'id est 2?

 

Merci d'avance de votre aide!

Edited by hphilg (see edit history)
Link to comment
Share on other sites

Excellente question!

 

1) Méthode non optimale :

 

Vous créez une catégorie qui contient tous vos produits sauf celle de la catégorie que vous ne souhaitez pas afficher.

Et vous l'affichez avec la méthode employée. And voilà !

 

 

2) Avec un peu plus de reflexion. Je ne pense pas que getProducts() permette d'exclure une catégorie (à vérifier). A mon avis il faut ruser avec une boucle pour afficher tous les produits dumpés en excluant ceux qui appartiennent à la catégorie en question.

 

Quelque chose du genre :

 

 

{$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', 2, true);}
{$inc = 0;}

{foreach from=$products}

{if $products.$inc.id_category !== id_de_la_categorie_a_excluse }

...Instructions...

{/if}

{$inc += 1}

{/foreach}

 

 

$products.$inc.id_category : C'est l'id de la catégorie du produit de la ligne en cours du tableau. D'ailleurs pensez à vérifier que la variable s'appelle bien id_category

Cas concret : $products.0.id_product est l'id du produit de la première ligne du tableau; 1 de la seconde, etc...

 

 

Mon code n'a pas du tout été testé et si un expert smarty passe dans le coin, merci de vérifier ça, notamment pour la façon d'incrémenter avec smarty et l'extraction de l'array ;-)

Link to comment
Share on other sites

Côté PHP:

global $cookie;
// On récupère les id_category actifs
$categories=Db::getInstance()->ExecuteS('select * from '._DB_PREFIX_.'category where active=1 order by id_category ASC');
$products=array();
// On liste chaque catégorie
foreach($categories as $category)
 {
	 //Si la catégorie n'est pas la catégorie 2, on ajoute à la variable products
	  if($category['id_category']!=2)
		 {
			   array_push($products,Product::getProducts($cookie->id_lang, 0, NULL, 'id_product','ASC',$category['id_category']));
		 }
}
//On assigne la variable products à smarty
$smarty->assign('produits',$products);

 

Et côté TPL tu récupères les données {$produits} que tu peux utiliser comme décrit ci-dessus avec des boucles foreach par exemple.

 

A noter:

Smarty n'est pas capable de faire ce genre de choses:

{$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', 2, true);}

Smarty est un moteur de template, il n'est là "que pour afficher" les variables.

Toutes les opérations dans la BDD, ou ici un appel à une méthode de la classe Product... doivent s'effectuer en amont dans le fichier PHP associé au TPL

Edited by franckm1000 (see edit history)
Link to comment
Share on other sites

Merci à vous deux pour vos réponses !

Je décortique vos 2 solutions (@Siteprojet, ne m'en veut pas mais j'exclue ta 1ere solution par contre je teste ta 2eme solution! :) )

Et je vous fais un retour rapidement !

a+

Link to comment
Share on other sites

Merci à vous deux pour vos réponses ! Je décortique vos 2 solutions (@Siteprojet, ne m'en veut pas mais j'exclue ta 1ere solution par contre je teste ta 2eme solution! :) ) Et je vous fais un retour rapidement ! a+

 

C'est ce que je te conseille.

 

Et merci franck ;-)

Link to comment
Share on other sites

Bonjour à tous,

 

Alors me voila de retour avec malheureusement des soucis ! (pour le moment, je n'ai testé que ton code franckm1000 mais testerait aussi le tien SIteProjet ! :) )

 

Alors pour etre plus explicite, j'essaie de modifier le code du module googlebase présent a cet endroit

http://www.prestashop.com/forums/topic/124794-module-google-base-new-beta-version/

la dernière version : googlebase_0_7_3_5

 

je me suis donc focaliser sur la fonction "post-process" que j'essaie de modifier

 

voici le code que j'ai modifié en m'inspirant de ce que vous m'avez fourni :

private function _postProcess()
{
// On récupère les id_category actifs
$categories=Db::getInstance()->ExecuteS('select * from '._DB_PREFIX_.'category where active=1 order by id_category ASC');
$products=array();
// On liste chaque catégorie
foreach($categories as $category)
    {
	 //Si la catégorie n'est pas la catégorie 2, on ajoute à la variable products
 if($category['id_category']!=2)
  {
  array_push($products,Product::getProducts($cookie->id_lang, 0, NULL, 'id_product','ASC',$category['id_category']));
  }
 //On assigne la variable products à smarty
 //$smarty->assign('produits',$products);
 //echo $products;
 }
 if($products)
 {
  if (!$fp = fopen($this->winFixFilename(Configuration::get($this->name.'_filepath')), 'w'))
  {
    $this->_mod_errors[] = $this->l('Error writing to feed file.');
    return;
  }

 

mais malheuresement maintenant mon fichier est vide !

 

j'ai commenté tout ce qui est lié à smarty car ce n'est pas pour afficher sur une page mais pour generer mon fichier pour google. Ais-je bien fait ?

 

Merci d'avance !

Link to comment
Share on other sites

Merci de ta réactivité!

je viens de vérifier et effectivement j'ai bien la fonction winFixFilename.

En fait le module sans modification fonctionne très bien sauf que je souhaite faire exactement ce que fait le module mais en excluant une ou plusieurs catégories. Et en regardant le code je me suis dis que la meilleure méthode était en modifiant la fonction "_postProcess"

Link to comment
Share on other sites

les exemples donnés ci dessous sont valable pour la version 1.5 de prestashop, mais pour la 1.4 c'est exactement le même principe

 

Perso, ce que je ferai c'est d'overrider la fonction getProducts en rajoutant "exclude":

 

public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false, $only_active = false, Context $context = null, $exclude = false)

 

et dans la requête sql tu as :

 

...
WHERE pl.`id_lang` = '.(int)$id_lang.
($id_category ? ' AND c.`id_category` = '.(int)$id_category : '').
($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').
...

 

tu remplaces cette petite partie par :

 

 

WHERE pl.`id_lang` = '.(int)$id_lang.
($id_category ? ' AND c.`id_category` = '.(int)$id_category : '').
($exclude ? ' AND c.`id_category` NOT IN('.$exclude.')' : '').
($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').

 

et si tu veux exclure une catégorie (exemple 22) :

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, true, null, 22);

 

si tu veux exclure plusieurs catégories (exemple 22,23 et24):

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, true, null, '22, 23, 24');

 

Si tu veux tous les produits sans exclure de catégories :

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, true, null);

Edited by coeos.pro (see edit history)
Link to comment
Share on other sites

Bonsoir.

 

Excellente idée le :

NOT IN('.$exclude.')

avec l'ajout de ce paramètre dans la fonction !

 

Par contre tu parles bien d'override, donc la modification se fait dans le module et pas dans le coeur, n'est-ce pas ?

Dans ce cas, comment modifier la requête .sql sans qu'elle ne le soit directement dans le core ? Ca n'est pas possible en 1.4 n'est-ce pas ?

 

Cordialement

Link to comment
Share on other sites

tu créé un fichier Product.php dans override/classes/Product.php, tu y mets :

 

<?php

class Product extends ProductCore
{

public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false, $only_active = false, Context $context = null, $exclude = false)
{

ici tu copies/colles la fonction getProducts de ton fichier classes/Product.php (le core) en effectuant la modification que j'ai indiqué sur la requête SQL

}

}

 

ensuite pour avoir tous les produits sauf une catégorie tu fais par exemple :

 

 

$products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, true, null, 22);

Edited by coeos.pro (see edit history)
Link to comment
Share on other sites

Ca n'est pas possible en 1.4 n'est-ce pas ?

l'override est possible depuis la 1.4, ce n'était pas possible sur la 1.3, par contre avec la 1.4 il n'y a que le front office qui peut être overridé, avec la prochaine version (1.5) le back office pourra être aussi overridé.

  • Like 1
Link to comment
Share on other sites

Super coeos.pro, c'est clair et très propre, je viens de l'adapter avec la 1.4 car la fonction getProducts diffère un peu avec la 1.5 (nom et nombre de paramètres différents). Dès que j'ai terminé, je vous fais un retour est met cela à disposition.

 

Merci à tous pour votre aide

Link to comment
Share on other sites

Alors j'avance mais ça bloque sur la requête SQL et je ne voit pas pourquoi ! (j'ai activé le debug SQL)

 

 

Notice

: Undefined index: active in

D:\xampp\htdocs\prestashop\modules\googlebase\googlebase.php

on line

752

Unknown column 'c.id_category' in 'where clause'

 

SELECT p.*, pl.* , t.`rate` AS tax_rate, m.`name` AS manufacturer_name, s.`name` AS supplier_name

FROM `ps_product` p

LEFT JOIN `ps_product_lang` pl ON (p.`id_product` = pl.`id_product`)

LEFT JOIN `ps_tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`

AND tr.`id_country` = 8

AND tr.`id_state` = 0)

LEFT JOIN `ps_tax` t ON (t.`id_tax` = tr.`id_tax`)

LEFT JOIN `ps_manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)

LEFT JOIN `ps_supplier` s ON (s.`id_supplier` = p.`id_supplier`)

WHERE pl.`id_lang` = 2 AND c.`id_category` NOT IN(5)

ORDER BY p.`id_product` ASC

voici mon fichier product.php présent dans override/classes

class Product extends ProductCore
{
public static function getProducts($id_lang, $start, $limit, $orderBy, $orderWay, $id_category = false, $only_active = false, $exclude = false)
{
 if (!Validate::isOrderBy($orderBy) OR !Validate::isOrderWay($orderWay))
  die (Tools::displayError());
 if ($orderBy == 'id_product' OR $orderBy == 'price' OR $orderBy == 'date_add')
  $orderByPrefix = 'p';
 elseif ($orderBy == 'name')
  $orderByPrefix = 'pl';
 elseif ($orderBy == 'position')
  $orderByPrefix = 'c';
 $rq = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
 SELECT p.*, pl.* , t.`rate` AS tax_rate, m.`name` AS manufacturer_name, s.`name` AS supplier_name
 FROM `'._DB_PREFIX_.'product` p
 LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product`)
 LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
  AND tr.`id_country` = '.(int)Country::getDefaultCountryId().'
  AND tr.`id_state` = 0)
 LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
 LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
 LEFT JOIN `'._DB_PREFIX_.'supplier` s ON (s.`id_supplier` = p.`id_supplier`)'.
 ($id_category ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').'
 WHERE pl.`id_lang` = '.(int)($id_lang).
 ($id_category ? ' AND c.`id_category` = '.(int)($id_category) : '').
 ($exclude ? ' AND c.`id_category` NOT IN('.$exclude.')' : '').
 ($only_active ? ' AND p.`active` = 1' : '').'
 ORDER BY '.(isset($orderByPrefix) ? pSQL($orderByPrefix).'.' : '').'`'.pSQL($orderBy).'` '.pSQL($orderWay).
 ($limit > 0 ? ' LIMIT '.(int)($start).','.(int)($limit) : '')
 );
 if ($orderBy == 'price')
  Tools::orderbyPrice($rq,$orderWay);
 return ($rq);
}
}
?>

 

et voici la ligne modifiée dans googlebase.php

 

 $products = Product::getProducts($this->id_lang, 0, NULL, 'id_product', 'ASC', NULL, false, 5);

 

j'ai ajouté `'._DB_PREFIX_.'category` c mais c'est pas mieux..apres j'ai une erreur sur le ORDER BY.

 

J'en suis sûr que j'y suis presque !

 

Merci d'avance pour votre aide

Link to comment
Share on other sites

effectivement, si tu ne renseignes pas category quand tu appelles la fonction getProducts, alors la table category n'est pas incluse dans la requête SQL, pour éviter ceci remplace la ligne

 

($id_category ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').'

 

par

 

(($id_category OR $exclude) ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').'

  • Like 1
Link to comment
Share on other sites

Ca marche ! par contre il y a certains produits qui sont présents dans 2 catégories et du coup il s'affichaient plusieurs fois alors j'ai ajouté un distinct dans la requete...est-ce que cela te semble bon/optimal ?

 

 SELECT DISTINCT p.*, pl.* , t.`rate` AS tax_rate, m.`name` AS manufacturer_name, s.`name` AS supplier_name
 FROM `'._DB_PREFIX_.'product` p
 LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product`)
 LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
  AND tr.`id_country` = '.(int)Country::getDefaultCountryId().'
  AND tr.`id_state` = 0)
 LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
 LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
 LEFT JOIN `'._DB_PREFIX_.'supplier` s ON (s.`id_supplier` = p.`id_supplier`)'.
 (($id_category OR $exclude) ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').'
 WHERE pl.`id_lang` = '.(int)($id_lang).
 ($id_category? ' AND c.`id_category` = '.(int)($id_category) : '').
 ($exclude ? ' AND c.`id_category` NOT IN('.$exclude.')' : '').
 ($only_active ? ' AND p.`active` = 1' : '').'
 ORDER BY '.(isset($orderByPrefix) ? pSQL($orderByPrefix).'.' : '').'`'.pSQL($orderBy).'` '.pSQL($orderWay).
 ($limit > 0 ? ' LIMIT '.(int)($start).','.(int)($limit) : '')
 );

Link to comment
Share on other sites

Donc je confirme que ca fonctionne parfaitement ! Merci à vous !

Comme prévu, voici le fichier product.php à placer dans le dossier "override/classes/" ainsi que le fichier googlebase modifié (je donne le lien de l'auteur de ce script : http://www.prestasho...w-beta-version/ )

 

la ligne modifiée est la 233. dans mon exemple j'exclue la catégorie dont l'id est 260

 

Des que j'ai le temsp je testerais les autres solutions ! :) mais pour le moment je doit essayer de résoudre mes problèmes de configuration du module socolissimo :)

 

 

Merci encore !

Product.php

googlebase.php

Edited by hphilg (see edit history)
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...