Magento – Get a custom attribute value from a configurable product added to the cart

cartconfigurable-product

I'm trying to get a custom attribute from every product on the shopping cart to disable a shipping method if the attribute is set to Yes on any added product.

It doesn't work for configurable products (It gets the attribute for the parent). I tested it on simple and grouped ones and it works.

Basically I don't know how to look for the attribute on the child product.

Here's my model:

class Si_Shipping_Model_Shipping extends Mage_Shipping_Model_Shipping
{
public function collectCarrierRates($carrierCode, $request)
{
    if (!$this->_checkCarrierAvailability($carrierCode, $request)) {
        return $this;
    }
    return parent::collectCarrierRates($carrierCode, $request);
}

protected function _checkCarrierAvailability($carrierCode, $request = null)
{
    foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
    {
        if($item->getProduct()->isConfigurable()){
         // Do something to get the overweight attribute value
        }else{
        if($item->getProduct()->getOverweight()){
                if($carrierCode == 'flatrate'){
                    return false;
                }
            }
            }   
    }

    return true;
}
}

config.xml

  <global>
<helpers>
  <shipping>
    <class>Si_Shipping_Helper</class>
  </shipping>
</helpers>
<models>
    <shipping>
        <rewrite>
            <shipping>Si_Shipping_Model_Shipping</shipping>
        </rewrite>
    </shipping>
</models>
<sales>
        <quote>
            <item>
                <product_attributes>
                    <overweight />
                </product_attributes>
            </item>
        </quote>
</sales>

Best Answer

You need to find the simple product in the cart that is associated to the configurable product and get the attribute from that one.
The simple cart item is linked through the configurable one through $item->getParentItemId(). So you should loop through all the cart items, not just visible ones until you find one that matches your needs.
Here is a possible way of doing it.

protected function _checkCarrierAvailability($carrierCode, $request = null)
{
    foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
    {
        if($item->getProduct()->isConfigurable()) {
            //loop through all products
            foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllItems() as $cartItem) {
               if ($cartItem->getParentItemId() == $item->getId()) {
                   //you found the simple product
                   if($item->getProduct()->getOverweight()) {
                        if($carrierCode == 'flatrate'){
                            return false;
                        }
                   }
                   break; //no need to search further
               }
           }
        } else {
            if($item->getProduct()->getOverweight()) {
                if($carrierCode == 'flatrate'){
                    return false;
                }
            }
        }   
    }
    return true;
}

What I described above can be used in the general case, when you need something from the simple product, but in your case is even more simple.
All you need is to find a product that is overweight. If you have one it means you cannot use flatrate.
You shouldn't care if the product is configurable or not. You just need one item. So instead of looping through getAllVisibleItems you should loop through getAllItems

protected function _checkCarrierAvailability($carrierCode, $request = null)
{
    foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllItems() as $item)
    {
        if($item->getProduct()->getOverweight()) {
            if($carrierCode == 'flatrate'){
                return false;
            }
        }
    }   
    return true;
}
Related Topic