Magento - Retrieve products with a specific attribute value

piaoling  2011-06-14 18:20:30
28 down vote accepted

Almost all Magento Models have a corresponding Collection object that can be used to fetch multiple instances of a Model.

To instantiate a Product collection, do the following

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

Products are a Magento EAV style Model, so you'll need to add on any additional attributes that you want to return.

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

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

There's multiple syntaxes for setting filters on collections. I always use the verbose one below, but you might want to inspect the Magento source for additional ways the filtering methods can be used.

The following shows how to filter by a range of values (greater than AND less than)

$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 greater than (lt) 130
$collection->addFieldToFilter(array(
        array('attribute'=>'orig_price','lt'=>'130'),
));

While this will filter by a name that equals one thing OR another.

$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'),            
));

A full list of the supported short conditionals (eq,lt, etc.) can be found in the _getConditionSql method in lib/Varien/Data/Collection/Db.php

Finally, all Magento collections may be iterated over (the base collection class implements on of the the iterator interfaces). This is how you'll grab your products once filters are set.

$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('name'=>'orig_price','eq'=>'Widget A'),
        array('name'=>'orig_price','eq'=>'Widget B'),           
));

foreach ($collection as $product) {
        //var_dump($product);
        var_dump($product->getData());
}
link|edit|flag
 
1  
very detailed answer. thanks! – Rick J Aug 27 '09 at 4:05
 
Thank you very much for the detailed answer. You have set me along the right path. I did a var_dump of the results from your example code. Because the attribute I am working with is a multiple select item I am getting a numeric id in the results so a text comparison is not working. E.G. $this->collection->addFieldToFilter(array( array('attribute'=>'cw_category','eq'=>'Aero'), array('attribute'=>'cw_category','eq'=>'Track'), array('attribute'=>'cw_category','eq'=>'Touring') )); Is returning 'cw_category' => string ',536,535,534' (length=12) – Christian Thamer Aug 27 '09 at 8:01
 
Can't specifically help you there without a lot of digging (StackOverflow rep is nice, but it doesn't pay the bills). Two avenues for you to pursue. First, as mentioned, checkout _getConditionSql for a list of all the possible comparison operators. You might be able to get by with a like clause or maybe an in. Secondly, if you checkout the PHPDoc for the addAttributeToFilter method on Mage_Eav_Model_Entity_Collection_Abstract, you'll see that one of the expected values of the first param is a Mage_Eav_Model_Entity_Attribute_Interface. That might lead you on the correct path. – Alan Storm Aug 27 '09 at 17:39
 
Alan, thanks for the additional tips. I went through the code for hours and had no luck. I did learn a lot more about Magento in the process though so I guess it isn't all bad. I managed to get the sql debugger working. It looks like for now I am going to just use the attribute ID in my filtering criteria. e.g. ...->addAttributeToFilter('cw_category','536') instead of ->addAttributeToFilter('cw_category','Aero') for example. – Christian Thamer Aug 28 '09 at 5:18
 
I've seen that as a common way of handling it. I think the way you're "supposed" to do this is instantiate and attribute object of the type you want, and pass that to one of the filtering methods. – Alan Storm Aug 28 '09 at 18:54

This is a follow up to my original question to help out others with the same problem. If you need to filter by an attribute, rather than manually looking up the id you can use the following code to retrieve all the id, value pairs for an attribute. The data is returned as an array with the attribute name as the key.

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;
}

Here is a function you can use to get products by their attribute set id. Retrieved using the previous function.

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;
}
link|edit|flag
   

I'm not a coder but interested in doing this. Can you give me the steps on where and how to implement this? I presume I copy and paste the code and modified the attributes that I'm searching for, right? Where do place these codes at?

link|edit|flag
   

I have added line

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

in app/code/core/Mage/Catalog/Block/Product/List.php on line 95 in function _getProductCollection()

and then call it in app/design/frontend/default/hellopress/template/catalog/product/list.phtml By writing code

__('Release Date: %s', $this->dateFormat($_product->getReleasedate())) ?>

Now it is working in Magento 1.4.x

link|edit|flag
   

Great post, thanks!

I'm able to get the id's but when l run getProductsByAttributeSetId(28) for example l don't get anything returned, why isn't it sending me an array of the product(s) that have this specific attribute value?

link|edit|flag
   

To Get TEXT attributes added from admin to front end on product listing page.

Thanks Anita Mourya

I have found there is two methods.. Let say product attribute called "na_author" is added from backend as text field.

METHOD 1. on list.phtml

FOR EACH PRODUCT LOAD BY SKU AND GET ATTRIBUTE INSIDE FOREACH

   $product =    Mage::getModel('catalog/product')->loadByAttribute('sku',$_product->getSku());

$author = $product['na_author']; ?>

By ".$author ."";} else{echo "";}?>

METHOD 2 Mage/Catalog/Block/Product/List.phtml OVER RIDE and set in 'local folder'

i.e. Copy FRom Mage/Catalog/Block/Product/List.phtml and PASTE TO

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

change the function by adding 2 lines shown in bold below.

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;

}

and you will be happy to see it....!!

 

类别 :  magento(258)  |  浏览(3691)  |  评论(0)
发表评论(评论将通过邮件发给作者):

Email: