Get configurable product options in product list (category view)

It is a pretty common task to display some product options like colour, size at the product list (category view) page in Magento. And it can not be done just with the default installation. Such decision is very reasonable as it is a hard task to load options for every configurable product on the page. Therefore, we tried to find the most efficient method of doing this, so below – there is one of the solutions that we came up with.
Before we begin, take a look at the related articles How to get configurable product options and attributes and Custom resource model for Magento product flat tables, where two ways of getting options of configurable products have been described.

The first one uses getConfigurableAttributesAsArray function. Applying it to every product can affect performance. The second way is – to use flat tables (it’s very interesting solution and such solution may be helpful in many situations).

However, it is time to describe another approach. While digging into core code you can notice that to generate associated product filters the getUsedProducts (see app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php file) method is called for every configurable product. The collection of subproducts is being loaded here. What we are going to do is to use catalog_product_collection_load_after event (dispatched in _afterLoad()) related to this collection to store all needed options for the particular configurable product. We create a simple model to store options data grabbed from the subproducts collection. So, when the time to display products comes up we will have all needed options in our storage. To make it clearer let’s put some code. In this example let’s display the available product colours.
Config file:

<?xml version="1.0"?>
<!--
/app/code/local/Atwix/ProductOptions/etc/config.xml 
-->
<config>
    <modules>
        <Atwix_ProductOptions>
            <version>1.0.0</version>
        </Atwix_ProductOptions>
    </modules>
    <global>
        <helpers>
            <atwix_productoptions>
                <class>Atwix_ProductOptions_Helper</class>
            </atwix_productoptions>
        </helpers>
        <models>
            <atwix_productoptions>
                <class>Atwix_ProductOptions_Model</class>
            </atwix_productoptions>
        </models>
    </global>
    <frontend>
        <events>
            <catalog_product_collection_load_after>
                <observers>
                    <atwix_productoptions>
                        <class>atwix_productoptions/observer</class>
                        <method>storeAttributes</method>
                    </atwix_productoptions>
                </observers>
            </catalog_product_collection_load_after>
        </events>
    </frontend>
</config>

Observer:

<?php
/* /app/code/local/Atwix/ProductOptions/Model/Observer.php */
class Atwix_ProductOptions_Model_Observer
{
    /**
     * Checks if needed collection catched and passes it to Storage Model to store options
     * @param $observer
     * @return $this
     */
    public function storeAttributes($observer)
    {
        $collection = $observer->getCollection();
        if ($collection instanceof Mage_Catalog_Model_Resource_Product_Type_Configurable_Product_Collection)
        {
            $storageModel = Mage::getSingleton('atwix_productoptions/storage');
            $storageModel->storeData($collection);
        }
        return $this;
    }
}

Model used to store options:

<?php
/* /app/code/local/Atwix/ProductOptions/Model/Storage.php */
class Atwix_ProductOptions_Model_Storage extends Mage_Core_Model_Abstract
{
    /**
     * options will be stored in this array 
     * @var null|array
     */
    protected $_attributes = null;

    /**
     * options labels
     * @var null|array
     */
    protected $_options = null;

    /**
     * Puts Color options to $_attributes array 
     * @param $collection
     * @return $this
     */
    public function storeData($collection)
    {
        foreach($collection->getItems() as $item){
            if ($color = $item->getColor()){
                $this->_attributes[$item->getParentId()]['color'][$color] = $this->getOptionLabel('color', $color);
            }
        }
        return $this;
    }

    /**
     * Retrieves option label by attribute name and value
     * stores all labels in array on first calling 
     * @param $attrName
     * @param $value
     * @return mixed
     */
    public function getOptionLabel($attrName, $value){
        if (!isset($this->_options[$attrName])){
            $attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', $attrName);
            $optArray = $attribute->getSource()->getAllOptions(false);
            foreach($optArray as $item){
                $this->_options[$attrName][$item['value']] = $item['label'];
            }
        }
        return $this->_options[$attrName][$value];
    }

    /**
     * Returns options for products 
     * @param product id $id  
     * @param $code
     * @return bool|array
     */
    public function getOptions($id, $code)
    {
        if (isset($this->_attributes[$id][$code])){
            return $this->_attributes[$id][$code];
        }
        return false;
    }
}

Helper class:

<?php
/* /app/code/local/Atwix/ProductOptions/Helper/Data.php */
class Atwix_ProductOptions_Helper_Data extends Mage_Core_Helper_Abstract
{
    protected $_storageModel = null;

    public function  __construct()
    {
        $this->_storageModel = Mage::getSingleton('atwix_productoptions/storage');
    }

    /**
     * gets options from storage and generates string
     * @param $id
     * @param $code
     * @return string
     */
    public function getConfigurableProductAttributeOptions($id, $code)
    {
        $values = $this->_storageModel->getOptions($id, $code);
        if ($values){
            return implode(', ',$values);
        }
        return '';
    }
}

And finally, if you place the following line:

<b><?php echo Mage::helper('atwix_productoptions')->getConfigurableProductAttributeOptions($_product->getId(), 'color'); ?></b></br>

to your template file (in our case it is app/design/frontend/base/default/template/catalog/product/list.phtml) somewhere after the construction:

<?php if($_product->isSaleable()): ?>

you will get something like this:
Magento product options - category view
The complete module code can be found here. If you know better/alternative way of getting configurable product options in the product list, you’re welcome to share your knowledge in the comments below.

Read more: