I'm trying to display a list of of the stock status for the simple products related to a configurable product. This is working fine except when for the first instance of the array when the related attribute 'Size' isn't display.
<?php $_helper = $this->helper('catalog/output'); ?>
<?php $_product = $this->getProduct(); ?>
<?php $instock = "Next Day"; ?>
<?php $outofstock = "4 to 7 Days"; ?>
<?php $conf = Mage::getModel('catalog/product_type_configurable')->setProduct($_product); ?>
<?php $col = $conf->getUsedProductCollection()->addAttributeToSelect('Size')->addFilterByRequiredOptions(); ?>
<ul>
<?php foreach($col as $simple_product){
$qty = intval(Mage::getModel('cataloginventory/stock_item')->loadByProduct($simple_product)->getQty());
$size = Mage::getModel('catalog/product')->load($simple_product->getId())->getAttributeText('Size');
?>
<li>
<?php
if ( $qty >= 1 )
{echo $qty, " ",$size," ",$instock;}
else
{echo $qty, " ",$size," ",$outofstock;} ?>
</li>
<?php } ?>
</ul>
The results set is looking like this:
99 Next Day
99 9 Next Day
99 8.5 Next Day
99 8 Next Day
99 7.5 Next Day
0 7 4 to 7 Days
99 12 Next Day
99 11.5 Next Day
99 11 Next Day
99 10.5 Next Day
99 10 Next Day
Any pointers on what I've got wrong and how to get the first attribute displayed?
To solve your issue was so much easier than to understand what is causing it! But let me address it in the correct order:
First of all, both addAttributeToSelect
and getAttributeText
actually operates with attribute_code
, not attribute_value
(which I believe you have as size, not Size).
So the first time Magento does $product->getData('Size')
inside the getAttributeText
, it returns null
.
When you pass the Size to getAttributeText
function, the size code gets replaced with Size for the particular attribute instance. How is it happening? Very simple: in the deepest layer of the methods chain, Magento makes next request to the DB:
SELECT `eav_attribute`.* FROM `eav_attribute` WHERE (`eav_attribute`.`attribute_code`='Size') AND (entity_type_id = :entity_type_id);
And if you have collate for your table as case-insensitive (*_ci), it will get the value no matter that actual attribute_code
is "size". You can read more about collate in official article and on SO.
So after the first getAttributeText('Size')
function every consecutive $product->getData('Size')
will return correct value.
Now returning to your script. Aside from size-Size issue you have few more little issues, but it would be great to deal with them for you to better understand Magento and php in general:
First of all, it's really a bad practice to use load
function inside the loop - especially two times in a row, especially with the product object. If your configurable product has a lot of simples, you'll get unnecessary memory and time losses. It is way better to add all the data you need to your collection
, and then use loaded products in the loop. BTW you've already added size to your collection using addAttributeToSelect
function. So the correct way to approach your issue would be:
$col = $conf->getUsedProductCollection()
->addAttributeToSelect('size')
->joinField(
'qty',
'cataloginventory/stock_item',
'qty',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left'
)->addFilterByRequiredOptions();
foreach($col as $simple_product){
$qty = (int)$simple_product->getQty();
$size = $simple_product->getAttributeText('size');
// do your logic
}
And second issue I wanted to mention, since you're in the .phtml
template file, it's required from you to follow Magento template standards - using close tags for you loops and cases:
<?php foreach($col as $simple_product):?>
<li>
<?php if ( $qty >= 1 ):?>
<!-- some html -->
<?php else:?>
<!-- some html -->
<?php endif:?>
</li>
<?php endforeach;?>