Manipuler les collections de produits

  • Par Magentix le 06/08/2010
  • Difficulté : 2/4

Manipuler les collections de produits Voici un petit aide mémoire sur la manipulation des collections de produits : filtres, limites, tris... Méthodes que l'on utilise régulièrement lors du développement d'un site e-commerce Magento...

Usage

Récupérer une collection de produits

Collection de produits

$products = Mage::getResourceModel('catalog/product_collection');
/* ou */
$products = Mage::getModel('catalog/product')->getCollection();

Les attributs exploitables par défaut sont :

entity_id, entity_type_id, type_id, sku, has_options, required_options, created_at, updated_at, is_salable, stock_item

Sélection d'un attribut spécifique

addAttributeToSelect

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('weight');

Sélection de tous les attributs

addAttributeToSelect

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('*');

Filtres sur les attributs de produits

addAttributeToFilter

$products = Mage::getResourceModel('catalog/product_collection')
            /* Produits activés */
            ->addAttributeToFilter('status',1)

            /* Produits dont les identifiants sont X,Y */
            ->addAttributeToFilter('entity_id',array('in'=>array(2,4)))

            /* Produits dont les identifiants ne sont pas X,Y */
            ->addAttributeToFilter('entity_id',array('nin'=>array(1,3)))

            /* Prix des produits compris entre X et Y */
            ->addAttributeToFilter('price',array('from' => 10, 'to' => 100))

            /* Poids des produits à partir de X */
            ->addAttributeToFilter('weight',array('from' => 100))

            /* Prix spécial (promotion) n'est pas égal à 0 */
            ->addAttributeToFilter('special_price',array('neq' => 0))

            /* La référence contient */
            ->addAttributeToFilter('sku',array('like' => '%P%'))

            /* La référence ne contient pas */
            ->addAttributeToFilter('sku',array('nlike' => '%A%'))

            /* Produits ajoutés entre le dd/mm/yyyy et le dd/mm/yyyy */
            ->addAttributeToFilter('created_at',array('from' => '2009-01-01', 'to' => '2011-01-01'))

            /* Produits visibles dans le catalogue et la recherche */
            ->addAttributeToFilter('visibility',array('in' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH));

Filtres sur les catégories de produits

addCategoryFilter

$category = Mage::getModel('catalog/category')->load(1);

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->addCategoryFilter($category);

Limiter le nombre de résultats

setPageSize

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->setPageSize(10);

Trier les résultats

addAttributeToSort

/* Trier sur un attribut spécifique */
$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->addAttributeToSort('price','asc');

/* Trier de façon aléatoire (Rand) */
$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name');  

$products->getSelect()->order(new Zend_Db_Expr('RAND()'));

Autres méthodes utiles

Autres méthodes

$products = Mage::getResourceModel('catalog/product_collection')
            /* Produits dont les identifiants sont X,Y */
            ->addIdFilter(array(2,4))

            /* Produits de la boutique en cours de consultation */
            ->addStoreFilter()

            /* Produits de la boutique dont l'identifiant est 1 */
            ->addStoreFilter(1)

            /* Sélectionner le prix final calculé */
            ->addFinalPrice()

            /* Sélectionner le prix le plus faible (produits avec options) */
            ->addMinimalPrice();

Collection de produits avec statistiques (Reports)

Reports

$products = Mage::getResourceModel('reports/product_collection')
            /* Total des ventes du produit */
            ->addOrderedQty()

            /* Total des paniers incluant le produit */
            ->addCartsCount()

            /* Total des ventres entre dd/mm/yyyy et dd/mm/yyyy */
            ->addOrdersCount('2009-01-01','2011-01-01')

            /* Total des consultations du produit entre dd/mm/yyyy et dd/mm/yyyy */
            ->addViewsCount('2009-01-01','2011-01-01');

Visualiser la requête générée

getSelect

$products = Mage::getResourceModel('catalog/product_collection');
echo $products->getSelect();
Exemples

Liste des produits en promotions

Promotions

$now = Mage::getModel('core/date')->timestamp(time());
$date = date('Y-m-d h:i:s', $now);

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->addAttributeToFilter('special_price',array('neq' => 0))
            ->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $date))
            ->addAttributeToFilter(array(
                        array('attribute' => 'special_to_date', 'date' => true, 'from' => $date),
                        array('attribute' => 'special_to_date', 'is' => new Zend_Db_Expr('null'))
            ));

Liste des nouveautés

Nouveautés

$now = Mage::getModel('core/date')->timestamp(time());
$date = date('Y-m-d h:i:s', $now);

$products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('name')
            ->addAttributeToFilter('news_from_date', array('date' => true, 'to' => $date))
            ->addAttributeToFilter(array(
                        array('attribute' => 'news_to_date', 'date' => true, 'from' => $date),
                        array('attribute' => 'news_to_date', 'is' => new Zend_Db_Expr('null'))
            ));

Liste des 5 produits les plus vendus

Bestsellers

$products = Mage::getResourceModel('reports/product_collection')
            ->addAttributeToSelect('name')
            ->addOrderedQty()
            ->addAttributeToSort('ordered_qty','desc')
            ->setPageSize(5);
21

Commentez cet article Manipuler les collections de produits

Pyksel Le 07/08/2010 à 21:45
Excellent article :)

Ce blog est de qualité super extra :)
#1
DnD Le 07/08/2010 à 23:17
Always on top !
#2
sinclairfr Le 08/08/2010 à 11:09
Une excellente cheat sheet, un grand bravo !
#3
Frédéric MARTINEZ Le 08/08/2010 à 11:53
Génial l'article (encore une fois).

Parfait pour aller chercher l'information.

Merci !
#4
Magentalliage Le 09/08/2010 à 09:24
Bravo, un aide mémoire très utile ! Merci
#5
Amine Le 09/08/2010 à 11:36
merci cousin, c'est très utile
#6
Magentix Le 10/08/2010 à 16:07
Merci pour les messages ;) Je pense que je publierais d'autres articles dans le même style sur les catégories, les users...
#7
Anthony Charrex Le 11/08/2010 à 08:41
Merci pour cet article ;)

Lors de la récupération d'une collection de produits, il est possible d'y appliquer des filtres afin de ne récupérer que des produits activés et visibles :

Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInSiteFilterToCollection($collection);
#8
Magentix Le 11/08/2010 à 09:19
Exact ! Bien vu ;) Avec 3 filtres pour la visibilité :

Mage::getSingleton('catalog/product_visibility')
->addVisibleInCatalogFilterToCollection($collection)
->addVisibleInSearchFilterToCollection($collection)
->addVisibleInSiteFilterToCollection($collection)
#9
come Le 16/08/2010 à 11:44
petite question sur la methode addAttributeToSelect :

j'ai constaté (avec le plugin beezup) que la méthode de récupération des attributs de type select/dropdown (et uniquement ceux là) ne sont pas exportés (valeur vide) dans le xml

la récupération via la ligne
$value = $p->getResource()->getAttribute($a)->getFrontend()->getValue($p);
(où $p est un produit de la collection et $a un attribut de type select/dropdown)
ne renvoie rien.

Un patch (dégueulasse) consiste à ajouter dans le foreach de la collection ce genre de chose:
$model2 = Mage::getModel('catalog/product');
$p2 = $model2->load($p->getId());
$value = $p2->getResource()->getAttribute($a)->getFrontend()->getValue($p2);

la valeur de l'attribut est alors bien rendue mais bon on ajoute une requete par produit de la collection ce qui est vraiment vraiment pas propre :$

j'ai essayé d'ajouter à la methode de base (dans le modele)
->addAttributeToSelect('*');

mais rien n'y fait les attributs de type select/dropdown sont vides

avez vous constaté ce problème ? y'a t'il un moyen de résoudre ça ?

j'espere avoir été compréhensible ;)
#10
Magentix Le 16/08/2010 à 12:07
Oui, plutôt étrange puisque l'attribut est déjà chargé dans la collection. Lors de mes tests cela ne posait pas de problème. L'enjeu du module est de limiter au maximum les requêtes car pour un gros catalogue cela peut devenir vite problématique... Je vais refaire quelques tests ;)
#11
come Le 16/08/2010 à 12:56
ok, bon courage.

le module que tu as fait est très bien mais j'ai l'impression que le problème vient plutôt de magento, j'avais rencontré le même soucis avec une extension custom pour exporter le catalogue produit en xml.

je suis intéressé si tu as une solution élégante (et si tu constate effectivement le problème)
#12
Magentix Le 16/08/2010 à 15:42
J'ai reessayé sur un Magento 1.4.0.1 vierge avec l'attribut "color". çà passe sans problème... Dans la gestion des labels de l'attribut une valeur est bien renseigné pour admin et pour le site ?

Tu peux également tenté d'analyser l'objet voir si l'attribut est bien pris en compte. En éditant le fichier "CatalogController.php" :

/* ... */
foreach($products as $p) {
Zend_debug::dump($p);
die;
}
/* ... */

Pour ma part avec l'attribut color j'obtient :
["color"] => string(1) "3"
#13
come Le 16/08/2010 à 17:27
ok je te remercie,

j'ai constaté la même chose que toi sur une install vierge de 1.4...

il se trouve que mon bug est sur une version 1.3 de magento, j'ai mis à jour ma magento avec les données sur une plateforme de test , il semblerait que ça passe maintenant...

reste à passer la prod maintenant :p

merci de ton aide en tout cas ! ^^
#14
come Le 17/08/2010 à 16:50
je reviens pour poster la solution qui était vraiment toute bête ;)

en fait les attributs qui ne s'exportaient pas n'étaient pas que les dropdown comme je le pensais... il s'agissait des attributs ayant le paramètre :
"Utilisé dans la liste de produits" à "non" dans la configuration des attributs . De fait les attributs n'étaient donc pas présents dans la collection malgré les addAttributeToSelect

passer le paramètre à "oui" a tout résolu

en espérant que ca aidera quelqu'un ;)
#15
Magentix Le 18/08/2010 à 12:43
Il me semble que cela se produit lorsque le mode Flat est activé. Dans ce cas cette option est en effet obligatoire ;)
#16
laurent Le 09/09/2010 à 21:00
Un grand merci pour cet article limpide !
Ton blog est vraiment top !
#17
jem Le 16/10/2010 à 21:32
Bonjour
Je ne comprends pas comment afficher tous les produits en promotions de la boutique
print_r($products = Mage::getResourceModel('catalog/product_collection')->addAttributeToSelect('special_price'));
Ce code m'affiche un tableau illisible, je cherche à afficher par ligne le nom du produit plus le prix spécial.

ps : super article
#18
teuf Le 16/01/2011 à 11:26
Pour les produits en promotion, la collection ne prend pas en compte que les promotions par règles de prix catalogue.
Aurais-tu un code qui prendrait en compte également ces produits en promo ?
#19
Tom Le 10/09/2011 à 10:07
Super article récapitulatif et une très bonne entrée en matière pour comprendre la philosophie objet de Magento et Zend !
#20
eddz Le 13/01/2012 à 10:29
Champion !!!
#21
Rédiger un commentaire

Cliquez pour générer un nouveau code

* champs obligatoires