78 votes

Magento - Récupérer les produits avec une valeur d'attribut spécifique

Dans mon bloc de code, j'essaie de récupérer de manière programmatique une liste de produits qui ont un attribut avec une valeur spécifique.

Sinon, si ce n'est pas possible, comment faire pour récupérer tous les produits, puis les filtrer pour n'afficher que les produits ayant un attribut spécifique ?

Comment effectuer une recherche en utilisant des filtres booléens standard ? AND ou OR pour correspondre à un sous-ensemble de mes produits ?

160voto

Alan Storm Points 82442

Presque tous les modèles Magento ont un objet Collection correspondant qui peut être utilisé pour récupérer plusieurs instances d'un modèle.

Pour instancier une collection de produits, procédez comme suit

$collection = Mage::getModel('catalog/product')->getCollection();

Les produits sont un modèle de style Magento EAV, vous devrez donc ajouter tous les attributs supplémentaires que vous souhaitez renvoyer.

$collection = Mage::getModel('catalog/product')->getCollection();

//fetch name and orig_price into data
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

Il existe plusieurs syntaxes pour définir des filtres sur les collections. J'utilise toujours la syntaxe verbeuse ci-dessous, mais vous pourriez vouloir inspecter la source Magento pour trouver d'autres façons d'utiliser les méthodes de filtrage.

L'exemple suivant montre comment filtrer par une plage de valeurs (supérieur à ET inférieur à)

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products whose orig_price is greater than (gt) 100
$collection->addFieldToFilter(array(
    array('attribute'=>'orig_price','gt'=>'100'),
)); 

//AND filter for products whose orig_price is less than (lt) 130
$collection->addFieldToFilter(array(
    array('attribute'=>'orig_price','lt'=>'130'),
));

Alors que celui-ci filtrera par un nom qui équivaut à une chose OU une autre.

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products who name is equal (eq) to Widget A, or equal (eq) to Widget B
$collection->addFieldToFilter(array(
    array('attribute'=>'name','eq'=>'Widget A'),
    array('attribute'=>'name','eq'=>'Widget B'),        
));

Une liste complète des conditionnels courts supportés (eq, lt, etc.) peut être trouvée dans le manuel de l'utilisateur. _getConditionSql méthode dans lib/Varien/Data/Collection/Db.php

Enfin, toutes les collections de Magento peuvent être itérées (la classe de collection de base implémente l'une des interfaces d'itération). C'est ainsi que vous récupérerez vos produits une fois les filtres définis.

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products who name is equal (eq) to Widget A, or equal (eq) to Widget B
$collection->addFieldToFilter(array(
    array('attribute'=>'name','eq'=>'Widget A'),
    array('attribute'=>'name','eq'=>'Widget B'),        
));

foreach ($collection as $product) {
    //var_dump($product);
    var_dump($product->getData());
}

0 votes

Merci beaucoup pour cette réponse détaillée. Vous m'avez mis sur la bonne voie. J'ai fait un var_dump des résultats de votre exemple de code. Comme l'attribut avec lequel je travaille est un élément à sélection multiple, j'obtiens un identifiant numérique dans les résultats, de sorte qu'une comparaison de texte ne fonctionne pas. Par exemple, $this->collection->addFieldToFilter(array( array('attribute'=>'cw_category','eq'=>'Aero'), array('attribute'=>'cw_category','eq'=>'Track'), array('attribute'=>'cw_category','eq'=>'Touring') )) ; Retourne 'cw_category' => string ',536,535,534' (length=12)

0 votes

Je ne peux pas vous aider de manière spécifique sans faire beaucoup de recherches (le représentant de StackOverflow est bien, mais il ne paie pas les factures). Vous avez deux pistes à suivre. Premièrement, comme mentionné, consultez _getConditionSql pour obtenir une liste de tous les opérateurs de comparaison possibles. Vous pourriez vous en sortir avec une clause like ou peut-être un in. Ensuite, si vous consultez la PHPDoc pour la méthode addAttributeToFilter sur Mage_Eav_Model_Entity_Collection_Abstract, vous verrez que l'une des valeurs attendues du premier paramètre est une Mage_Eav_Model_Entity_Attribute_Interface. Cela pourrait vous mettre sur la bonne voie.

0 votes

Alan, merci pour ces conseils supplémentaires. J'ai parcouru le code pendant des heures et je n'ai pas eu de chance. J'ai appris beaucoup plus sur Magento dans le processus, donc je suppose que ce n'est pas si mal. J'ai réussi à faire fonctionner le débogueur sql. Il semble que pour le moment je vais juste utiliser l'ID de l'attribut dans mes critères de filtrage. par exemple ...->addAttributeToFilter('cw_category','536') au lieu de ->addAttributeToFilter('cw_category','Aero') par exemple.

7voto

Christian Points 490

Il s'agit d'un suivi de ma question initiale pour aider d'autres personnes ayant le même problème. Si vous avez besoin de filtrer par un attribut, plutôt que de rechercher manuellement l'identifiant, vous pouvez utiliser le code suivant pour récupérer toutes les paires identifiant-valeur pour un attribut. Les données sont renvoyées sous la forme d'un tableau dont la clé est le nom de l'attribut.

function getAttributeOptions($attributeName) {
    $product = Mage::getModel('catalog/product');
    $collection = Mage::getResourceModel('eav/entity_attribute_collection')
              ->setEntityTypeFilter($product->getResource()->getTypeId())
              ->addFieldToFilter('attribute_code', $attributeName);

    $_attribute = $collection->getFirstItem()->setEntity($product->getResource());
    $attribute_options  = $_attribute->getSource()->getAllOptions(false);
    foreach($attribute_options as $val) {
        $attrList[$val['label']] = $val['value'];
    }   

    return $attrList;
}

Voici une fonction que vous pouvez utiliser pour obtenir des produits par leur id de jeu d'attributs. Récupéré à l'aide de la fonction précédente.

function getProductsByAttributeSetId($attributeSetId) {
   $products = Mage::getModel('catalog/product')->getCollection();
   $products->addAttributeToFilter('attribute_set_id',$attributeSetId);

   $products->addAttributeToSelect('*');

   $products->load();
   foreach($products as $val) {
     $productsArray[] = $val->getData();
  }

  return $productsArray;
}

5voto

verheesj Points 371
$attribute = Mage::getModel('eav/entity_attribute')
                ->loadByCode('catalog_product', 'manufacturer');

$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
            ->setAttributeFilter($attribute->getData('attribute_id'))
            ->setStoreFilter(0, false);

$preparedManufacturers = array();            
foreach($valuesCollection as $value) {
    $preparedManufacturers[$value->getOptionId()] = $value->getValue();
}   

if (count($preparedManufacturers)) {
    echo "<h2>Manufacturers</h2><ul>";
    foreach($preparedManufacturers as $optionId => $value) {
        $products = Mage::getModel('catalog/product')->getCollection();
        $products->addAttributeToSelect('manufacturer');
        $products->addFieldToFilter(array(
            array('attribute'=>'manufacturer', 'eq'=> $optionId,          
        ));

        echo "<li>" . $value . " - (" . $optionId . ") - (Products: ".count($products).")</li>";
    }
    echo "</ul>";
}

3voto

Pragnesh Karia Points 106

Pour obtenir TEXT attributs ajoutés depuis l'administration vers le front-end sur la page de liste des produits.

Merci Anita Mourya

J'ai constaté qu'il existe deux méthodes. Disons que l'attribut du produit appelé "na_author" est ajouté depuis le backend comme champ de texte.

MÉTHODE 1

sur list.phtml

<?php $i=0; foreach ($_productCollection as $_product): ?>

POUR CHAQUE PRODUIT CHARGER PAR SKU ET OBTENIR L'ATTRIBUT DANS FOREACH

<?php
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$_product->getSku());
$author = $product['na_author'];
?>

<?php
if($author!=""){echo "<br /><span class='home_book_author'>By ".$author ."</span>";} else{echo "";}
?>

MÉTHODE 2

Mage/Catalog/Block/Product/List.phtml OVER RIDE et mettre dans le 'dossier local'.

c'est-à-dire Copie de

Mage/Catalog/Block/Product/List.phtml

et coller dans

app/code/local/Mage/Catalog/Block/Product/List.phtml

modifier la fonction en ajoutant 2 lignes indiquées en gras ci-dessous.

protected function _getProductCollection()
{
       if (is_null($this->_productCollection)) {
           $layer = Mage::getSingleton('catalog/layer');
           /* @var $layer Mage_Catalog_Model_Layer */
           if ($this->getShowRootCategory()) {
               $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
           }

           // if this is a product view page
           if (Mage::registry('product')) {
               // get collection of categories this product is associated with
               $categories = Mage::registry('product')->getCategoryCollection()
                   ->setPage(1, 1)
                   ->load();
               // if the product is associated with any category
               if ($categories->count()) {
                   // show products from this category
                   $this->setCategoryId(current($categories->getIterator()));
               }
           }

           $origCategory = null;
           if ($this->getCategoryId()) {
               $category = Mage::getModel('catalog/category')->load($this->getCategoryId());

               if ($category->getId()) {
                   $origCategory = $layer->getCurrentCategory();
                   $layer->setCurrentCategory($category);
               }
           }
           $this->_productCollection = $layer->getProductCollection();

           $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

           if ($origCategory) {
               $layer->setCurrentCategory($origCategory);
           }
       }
       **//CMI-PK added na_author to filter on product listing page//
       $this->_productCollection->addAttributeToSelect('na_author');**
       return $this->_productCollection;

}

et vous serez heureux de le voir.... !!

0voto

Anita Mourya Points 9

J'ai ajouté la ligne

$this->_productCollection->addAttributeToSelect('releasedate');

sur

app/code/core/Mage/Catalog/Block/Product/List.php on line 95

en fonction _getProductCollection()

et l'appeler ensuite dans

app/design/frontend/default/hellopress/template/catalog/product/list.phtml

En écrivant du code

<div><?php echo $this->__('Release Date: %s', $this->dateFormat($_product->getReleasedate())) ?>
</div>

Il fonctionne maintenant dans Magento 1.4.x.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X