CMS Block Caching Issue in Magento EE 1.14.2

cachecmscms-blockee-1.14.2.0static-block

I have an issue that seems to be related to the caching of CMS static blocks.

I have a cms page and within that page I am rendering a number of cms static blocks. A simplified version of the CMS page content looks like this:

<div class="cms-block-1">{{block type="cms/block" block_id="banner_home"}}</div> 
<div class="cms-block-2">{{block type="cms/block" block_id="promo_home_1_1"}}</div> 
<div class="cms-block-3">{{block type="cms/block" block_id="promo_home_1_2"}}</div> 
<div class="cms-block-4">{{block type="cms/block" block_id="promo_home_2_1"}}</div> 
<div class="cms-block-5">{{block type="cms/block" block_id="promo_home_2_2"}}</div> 
<div class="cms-block-6">{{block type="cms/block" block_id="promo_home_2_3"}}</div> 
<div class="cms-block-7">{{block type="cms/block" block_id="promo_home_3_1"}}</div> 
<div class="cms-block-8">{{block type="cms/block" block_id="promo_home_3_2"}}</div>

The page loads as expected immediately after the block cache is cleared, that page looking something like this:

<div class="cms-block-1">banner content</div> 
<div class="cms-block-2">promo_home_1_1 content</div> 
<div class="cms-block-3">promo_home_1_2 content</div> 
<div class="cms-block-4">promo_home_2_1 content</div> 
<div class="cms-block-5">promo_home_2_2 content</div> 
<div class="cms-block-6">promo_home_2_3 content</div> 
<div class="cms-block-7">promo_home_3_1 content</div> 
<div class="cms-block-8">promo_home_3_1 content</div>

However after the inital page load, every subsequent page load the content is incorrect. It looks like this:

<div class="cms-block-1">banner content</div> 
<div class="cms-block-2">promo_home_1_1 content</div> 
<div class="cms-block-3">promo_home_1_2 content</div> 
<div class="cms-block-4">promo_home_1_1 content</div> 
<div class="cms-block-5">promo_home_1_2 content</div> 
<div class="cms-block-6">promo_home_2_1 content</div> 
<div class="cms-block-7">promo_home_2_2 content</div> 
<div class="cms-block-8">promo_home_2_3 content</div>

In the second example you can see the first two promos are correct, however everything after that is displaying the wrong content for the block_id. Also, block promo_home_1_1 and promo_home_1_2 are both rendered twice and promo_home_3_1 and promo_home_3_2 are never rendered. Its like the mapping between block_id and its associated static block content is being mixed up somehow. This is related to caching as if block cache isn't enabled then I no longer see the problem.

Also, it's probably worth noting that this page used to work on EE 1.13, however after upgrading to EE 1.14.2 this problem has started occurring.

I realise its pretty hard to say whats wrong without knowing what else is going on in the system but I am hoping someone might be able to give me at least some more direction here as I am running out of ideas.

Update:

I also tried this with widgets, e.g

<div class="cms-block-1">{{widget type="cms/widget_block" template="cms/widget/static_block/default.phtml" block_id="63"}}</div>
<div class="cms-block-2">{{widget type="cms/widget_block" template="cms/widget/static_block/default.phtml" block_id="64"}}</div>
<div class="cms-block-3">{{widget type="cms/widget_block" template="cms/widget/static_block/default.phtml" block_id="65"}}</div>

In this case all 3 blocks returned the same content even though the ids are pointing to different blocks in the database. When the cache is cleared the block returned will sometimes change, but all three widgets will still have the same content.

Best Answer

Ok so I have found the cause of this problem and it seems to be a problem in core magento.

There is a new _construct method added to Mage_Cms_Block_Block in magento 1.14.2 which contains the following code.

/**
 * Initialize cache
 *
 * @return null
 */
protected function _construct()
{
    /*
    * setting cache to save the cms block
    */
    $this->setCacheTags(array(Mage_Cms_Model_Block::CACHE_TAG));
    $this->setCacheLifetime(false);
}

This is effectively turning on caching for cms blocks. No cache key is set so it falls back to the Mage_Core_Block_Abstract::getCacheKeyInfo which uses the name of the block in layout. In this case we aren't actually using a layout xml file to add the block and there is no name set. Magento seems to try and handle this by setting something like ANONYMOUS_78 as the name. However for some reason this doesn't seem to be working 100% hence the duplicates I was seeing.

My solution was to override the Mage_Cms_Block_Block class in my own extension and add a new method to set the cache key explicitly to the block id rather than an assigned value. The class looks like this:

/**
 * Override cms/block to add cache key. This started being a problem as of EE 1.14.2 when the _construct
 * method was added which turns on caching for cms blocks
 */
class Mysite_Cms_Block_Block extends Mage_Cms_Block_Block
{

    /**
     * If this block has a block id, use that as the cache key.
     *
     * @return array
     */
    public function getCacheKeyInfo()
    {
        if ($this->getBlockId()) {
            return array(
                Mage_Cms_Model_Block::CACHE_TAG,
                Mage::app()->getStore()->getId(),
                $this->getBlockId(),
                (int) Mage::app()->getStore()->isCurrentlySecure()
            );
        } else {
            return parent::getCacheKeyInfo();
        }
    }
}

This seems to have resolved the issue.

Update:

It looks like this same problem also exists in CE 1.9.2

Related Topic