Voici mon code:
$catIds = array(7,8,9);
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect("*");
->addAttributeToFilter('category_ids', array('nin' => $catIds));
Je veux que tous les produits ne figurent pas dans la liste des identifiants de catégorie, mais mon code n'a pas donné le résultat attendu. Veuillez me montrer le chemin, merci.
magento-1
filter
product-collection
category-products
Lan Nguyen
la source
la source
Réponses:
Vous devez rejoindre le tableau contenant les relations catégorie / produit.
Une variation de la collection que j'utilise pour trouver tous les produits DANS une liste de catégories devrait faire l'affaire pour vous:
(non testé, mais devrait vous mettre sur la bonne voie)
réf: http://www.proxiblue.com.au/blog/Collection_of_products_in_all_child_categories/
la source
Le code suivant fonctionnera pour vous:
la source
J'ai trouvé un moyen un peu meilleur de le faire, en utilisant un anti-jointure (Magento 1.9).
Avantages de cette approche
L'avantage de cela par rapport à la réponse d'origine est que vous n'obtiendrez pas de faux positifs, ce qui est plus rapide et moins sujet aux erreurs. Par exemple, supposons que vous ayez un seul produit:
Vous voulez "trouver tous les produits qui ne s'y trouvent pas
category 3
, puis les ajouter àcategory 3
" . Vous exécutez donc uneNOT IN
requête et elle renverra deux lignes(name | category_id)
:Pas de problème, Magento ne renverra toujours que le premier résultat, puis vous l'ajouterez. Sauf ! La deuxième fois que cette requête est exécutée, vous obtenez les mêmes résultats:
Et Magento vous dira que vous n'avez pas encore ajouté cette chemise
category 3
. En effet, lorsqu'un produit appartient à plusieurs catégories, il y aura plusieurs lignes dans la table "catalog_product_entity" . Et donc unLEFT JOIN
retournera plusieurs résultats.Ceci n'est pas souhaitable car
in_array($categoryThree, $product->getCategories())
), ce qui signifie que vous parcourrez les résultats inutiles. Cela rendra votre script / code plus lent, surtout avec de gros inventaires.Solution
La requête SQL générée ressemblera à ceci:
Explication:
Compte tenu des tables de relation produit et <=> catégorie de produit:
catalog_product_entity
+-----------+ | ENTITY_ID | +-----------+ | 423 | | 424 | | 425 | +-----------+
catalog_category_product
+-------------+------------+ | CATEGORY_ID | PRODUCT_ID | +-------------+------------+ | 3 | 423 | | 123 | 424 | | 3 | 425 | +-------------+------------+
Votre requête dit "donnez-moi toutes les lignes dans " catalog_product_entity " et collez-la dans la colonne" category_id "de " catalog_category_product " . Ensuite, donnez-moi simplement les lignes que category_id = 124" .
Parce que c'est une jointure gauche, elle aura toujours les lignes de "catalog_product_entity" . Pour toutes les lignes qui ne peuvent pas être rapprochées, ce sera
NULL
:Résultat
+-------------+-------------+ | ENTITY_ID | CATEGORY_ID | +-------------+-------------+ | 423 | NULL | | 424 | 123 | | 425 | NULL | +-------------+-------------+
À partir de là, la requête dit alors "ok, donnez-moi maintenant tout où le category_id est NULL" .
la source
Pas aussi simple que cela puisse paraître.
Voici l'option basée sur GROUP_CONCAT car sa limite par défaut (1024 mais pourrait être augmentée bien sûr) devrait être correcte avec les ID de catégorie de produits séparés par des virgules.
De plus (si vous n'aimez pas GROUP_CONCAT), vous pouvez utiliser WHERE product_id NOT IN dans une sous-requête d'un ID de produit sont en fait dans les catégories que vous devez exclure (ne pas les donner ici).
L'approche anti-jointure d'une autre réponse fonctionnera également. Mais dans ce cas, vous ne pouvez pas facilement ajouter des conditions supplémentaires.
la source