3
votes

I'm having problems with a foreach loop in a magento template:

$cats = Mage::helper('catalog/category')->getStoreCategories();
foreach ($cats as $cat) {
    if($cat->getIsActive()&&$cat->getProductCount()) {
        echo "<div class=\"grid_6\">";
        echo $this->getLayout()->createBlock('catalog/product_new')
            ->setTemplate('catalog/product/new.phtml')
            ->setCategoryId($cat->getId())
            ->setColumnCount(2)
            ->setBlockTitle("Just Added in <a href=".$cat->getUrl().">".$cat->getName()."</a>")
            ->toHtml();
        echo "</div>";
    }
}

Results in an identical block being repeated 4 times (I have 4 main categories) when it should show 4 different blocks, one for each category. It's as if the $cat->getId(), $cat->getName() and $cat->getUrl() statements are not being updated on each new iteration.

What am I doing wrong here?

Thanks...

2
Have you done a dump of $cats to see if the data stored inside is what you expect it to be?Jrod
Hi Jrod - yes I have and it is. If I echo $cat->getName() I get the right cat name... It's this getLayout command that is somehow not getting the right data.gpcola

2 Answers

7
votes

Just a guess here, but it looks like the catalog/product_new block wasn't designed to be used multiple times on one request. If you look at the class definition in Mage_Catalog_Block_Product_New, its pseudo-constructor includes the following

    $this->addData(array(
        'cache_lifetime'    => 86400,
        'cache_tags'        => array(Mage_Catalog_Model_Product::CACHE_TAG),
    ));

The presence of a cache_lifetime and cache_tags property are hints to Magento's Layout rendering system that this block should be cached.

So, what's happening is the first time you render the block, the results are cached. The next time you render the block, instead of re-rendering this the results are pulled out of cache.

My advice here would be to create a custom code module, write a new block class that extends the old block class and redefines either _construct or getCacheKeyInfo in a such a way that you're "allowed" to render the Block multiple times.

0
votes

You don't need to override the block, you can just disable caching for the block at render time by adding ->setCacheLifetime(NULL) right before ->toHtml(). If the containing block is already cached then there is probably no benefit to caching the child blocks anyway.