1

I am currently developing a product configurator. I am submitting a form which sends the admin option values of my custom attributes via POST to a controller action. If I use the current store's attribute option labels all is working just fine, the product collection is filtered correctly and a simple product which is associated to a configurable product is returned. Sadly I am using the admin values for form and URL generation because the default swedish store values contain too many special characters.

So my question is: how do I get the right product from my collection when using the admin option values or more specific, how do I get the admin option value's ID like using this for the default store's values:

$id = Mage::getResourceModel('catalog/product')
                                    ->getAttribute($key)
                                    ->getSource()
                                    ->getOptionId($value); 

I already tried filtering by addStoreFilter(0), but that didn't work either. I already read that it could have something to do with flat tables being used in default store but not for admin, but I am rather unexperienced with Magento, so I don't really understand the difference using flat tables and what that really means.

Here is my last question concerning the filtering for reference: addFieldToFilter doesn't return the right product for selected attribute values

Here is my getProduct() function:

public function getProduct($attributes)
    {

        Mage::Log($attributes);

        $productModel = Mage::getModel('catalog/product');

        //Get Product Collection
        $collection = $productModel->getCollection()


        //Filter for Selected Product
        $collection->addAttributeToSelect('status');
        $collection->addAttributeToSelect('doorconfig_enable');
        $collection->addAttributeToFilter('doorconfig_enable',array('eq' => 1));

        foreach ($attributes as $key => $value) 
        {
            $collection->addAttributeToSelect($key);

            $id = Mage::getResourceModel('catalog/product')
                                    ->getAttribute($key)
                                    ->getSource()
                                    ->getOptionId($value);

            $collection->addAttributeToFilter($key,
                array(
                        'eq' => $id
                     )
            );

        }

        $selection = $collection->getSelect()->__toString();

        Mage::Log($selection);

        Mage::log($collection->getSize(),null,'custom.log');

        $product = $collection->getFirstItem();

        return $product;

    }
  • Where are you running the query? (admin app, or frontend app?) – Alan Storm Aug 6 '13 at 5:05
  • I am using the app/design/frontend folder and my configurator is running on the homepage, which should mean the code is running on the frontend app I guess :) – ericstumper Aug 6 '13 at 10:00
  • Yes, you're in the frontend app (Some collections behave differently depending on where they are) – Alan Storm Aug 6 '13 at 17:03
4

Like all of Magento, the answer's in the source — all you need to do is go digging (or hop to then end of this post).

First, find the class for the attribute source

$source = Mage::getResourceModel('catalog/product')
->getAttribute('color')
->getSource();        
var_dump(get_class($source));
exit;

In modern versions of Magento, this should point to the class Mage_Eav_Model_Entity_Attribute_Source_Table, which is located at

#File: app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php
class Mage_Eav_Model_Entity_Attribute_Source_Table extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
    //...
}

Next, we'll look for the definition of the getOptionId method on this class and/or it's parent classes. We'll find it in the Mage_Eav_Model_Entity_Attribute_Source_Abstract class

#File: app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Abstract.php
public function getOptionId($value)
{
    foreach ($this->getAllOptions() as $option) {
        if (strcasecmp($option['label'], $value)==0 || $option['value'] == $value) {
            return $option['value'];
        }
    }
    return null;
}

Examining this method, we can see if works by foreaching over a list of options from the getAllOptions method. So let's look at this method's definition.

#File: app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
    $storeId = $this->getAttribute()->getStoreId();
    if (!is_array($this->_options)) {
        $this->_options = array();
    }
    if (!is_array($this->_optionsDefault)) {
        $this->_optionsDefault = array();
    }
    if (!isset($this->_options[$storeId])) {
        $collection = Mage::getResourceModel('eav/entity_attribute_option_collection')
            ->setPositionOrder('asc')
            ->setAttributeFilter($this->getAttribute()->getId())
            ->setStoreFilter($this->getAttribute()->getStoreId())
            ->load();
        $this->_options[$storeId]        = $collection->toOptionArray();
        $this->_optionsDefault[$storeId] = $collection->toOptionArray('default_value');
    }
    $options = ($defaultValues ? $this->_optionsDefault[$storeId] : $this->_options[$storeId]);
    if ($withEmpty) {
        array_unshift($options, array('label' => '', 'value' => ''));
    }

    return $options;
}

Ah ha! Now we're on to something. This appears to be the method that loads all the option information. Specifically, we're interested in

$storeId = $this->getAttribute()->getStoreId();

So, Magento gets the store ID for the options to load from the attribute. This means you should be able to do something like the following (replacing color and red with your own variables, of course)

    //get the attribute
    $attribute = Mage::getResourceModel('catalog/product')
    ->getAttribute('color');

    //set the store id on the attribute
    $attribute->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID);

    //get the source
    $source = $attribute->getSource();

    //get the id
    $id = $source->getOptionId('red');
  • 1
    Sorry for my late reply, just got time to continue the project :) Thank you so much for this more than detailed answer! This works like a charm and I even understand where to look next time! – ericstumper Aug 23 '13 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.