Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I filter a magento collection by a select drop-down attribute?

In magento, I have an attribute called cl_designer, which is a select drop-down option. I want to filter the products collection on it, like this:

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('cl_designer', array('like' => $filter));

But it doesn't work! When I print out the query with $collection->getselect(), I see that it is comparing $filter to catalog_product_entity_int.value. But this is wrong, because for select options, catalog_product_entity_int.value is the option_id, NOT the value. So how do I make it filter on the actual option value?

like image 352
Benubird Avatar asked Feb 08 '13 18:02

Benubird


People also ask

How to sort a collection in Magento by attributes?

Magento is an EAV system that gives access to the addAttributeToFilter () method which can take a larger range of arguments as compared to the general addFieldToFilter () filter method. You can also sort a collection in Magento by attributes in ascending, descending or random order.

What is a collection in Magento?

Magento collections represent an efficient way of grouping models together and it’s an easy option of grabbing a group of models from the database with almost little to no SQL code (thanks to its unique methods). Collections are tricky to work with, but they offer extensive data about products, customers, categories, attributes, etc.

Where does Magento load product data from?

By default, Magento only loads the simple data found in the catalog_product_entity table, which includes IDs, SKUs, Entity Type IDs, etc. You can also check out how to configure Magento Attributes blog post. Check out these convenient methods for adding further product attributes:

What is Stack Exchange Magento?

Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It only takes a minute to sign up. Sign up to join this community Anybody can ask a question


2 Answers

Assuming an example drop-down attribute named size contains the following options:

id    value
22    'small'
23    'medium'
24    'large'

and you want to filter your collection by 'medium' options:

Filter by drop-down option value

To filter a product collection by option value of a product's (custom) drop-down attribute:

$sAttributeName = 'size';
$mOptionValue = 'medium';
$collection = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect('*')
    ->addFieldToFilter(
        $sAttributeName,
        array(
            'eq' => Mage::getResourceModel('catalog/product')
                        ->getAttribute($sAttributeName)
                        ->getSource()
                        ->getOptionId($mOptionValue)
        )
    );

Filter by drop-down option id

To filter a product collection by a option id of a product's (custom) drop-down attribute:

$sAttributeName = 'size';
$mOptionId = 23;
$collection = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect('*')
    ->addFieldToFilter(
        $sAttributeName,
        array('eq' => $mOptionId)
    );
like image 141
Jürgen Thelen Avatar answered Oct 31 '22 17:10

Jürgen Thelen


In short, like this:

$collection->
    addAttributeToFilter(
        array(
            array('attribute' => 'cl_designer', 'eq' => ''),
            array('attribute' => 'cl_designer', 'neq' => '')
        ))->
    joinTable(array('cl_designer_value'=>'eav_attribute_option_value'),'option_id = cl_designer', array('cl_designer_value' => 'value'))->
    addAttributeToFilter('cl_designer_value', array('like' => $filter));

The first addAttributeToFilter is needed to make it include the right catalog_product_entity_int table, and join it properly - by entity_id, attribute_id, and store_id. Next we use joinTable to connect to eav_attribute_option_value.

joinTable is complicated. The first argument is an array of tables to join, of the form alias => tablename. The tablename can be the raw name (like here), or the standard magento slash notation. The second argument is a string of the form "primary=attribute". Whatever is on the left of the = is assumed to be the column in this table that you want to use to join on, and whatever is after the = is assumed to be an attribute code. It then converts the attribute code given into a proper table.column to use in the join, BUT it does not add the table if missing - that's why we needed the first addAttributeToFilter.

The next argument to joinTable is also required, and is an array of the form alias => column, each entry of which is available for reference by its alias - so I specified array('cl_designer_value' => 'value'), which means that I can refer to cl_designer_value.value (tablealias.column) as cl_designer_value.

After the joinTable, I can now treat cl_designer_value as any other attribute code, and use it normally.

Keep in mind that joinTable joins a table by attribute code, but also that once you have joined one, the attribute code you specify in the fields array (third argument) is then available for use in your next join. So you can chain several calls to joinTable together, if you need to, although to be fair I can't really think of when you would.

like image 43
Benubird Avatar answered Oct 31 '22 18:10

Benubird