What would be the easiest way to create a FPC hole punch for static block (cms block)?
Let's say I have a static block that calls another block inside that has behaviour I want to be dynamic on every page load.
3 Answers 3
The easiest way I've found to holepunch CMS blocks in Magento Enterprise's Full Page Caching module has a few steps:
First, let's look at the directory structure required:
BranchLabs/CacheBuster/
Block/Cms.php # We inherit almost all functions from the Mage CMS
block, only overriding the "getCacheKeyInfo" function.
We do this to set the CMS block ID for later use by
our placeholder model.
etc/cache.xml # Here we target our module's version of the CMS block
and set their cache lifetimes to 0.
Model/Placeholder.php # This module is responsible for freshly rendering our
CMS blocks every time they're requested.
With that top-down understanding in mind here's how to fill those files out.
Create your own block class that extends the built in Magento CMS block. You'll need to override the "getCacheKeyInfo" function as follows too:
<?php // BranchLabs/CacheBuster/Block/Cms.php class BranchLabs_CacheBuster_Block_Cms extends Mage_Cms_Block_Block { // Used to set the cache placeholder attribute definitions, required in // the placeholder's "_renderBlock" function. public function getCacheKeyInfo() { return array('block_id' => $this->getBlockId()); } }Set up the placeholder model that is responsible for rendering out our CMS block without applying the cache.
<?php // BranchLabs/CacheBuster/Model/Placeholder.php class BranchLabs_CacheBuster_Model_Placeholder extends Enterprise_PageCache_Model_Container_Abstract { public function applyWithoutApp(&$content) { return false; } protected function _getCacheId() { $id = 'CACHEBUSTER_HOLEPUNCH_' . microtime() . '_' . rand(0,99); return $id; } /** * CacheBuster doesn't cache data! Do nothing. */ protected function _saveCache($data, $id, $tags = array(), $lifetime = null) { return $this; } /** * Render fresh block content. * * @return false|string */ protected function _renderBlock() { $block = $this->_placeholder->getAttribute('block'); $block = new $block; // Get the block_id attribute we originally set in our CMS block's // getCacheKeyInfo function. $block_id = $this->_placeholder->getAttribute('block_id'); $block->setBlockId($block_id); $block->setLayout(Mage::app()->getLayout()); return $block->toHtml(); } }Set up cache.xml to target our newly created CMS block and render using our newly created placeholder.
<!-- BranchLabs/CacheBuster/etc/cache.xml --> <?xml version="1.0" encoding="UTF-8"?> <config> <placeholders> <arbitrary_unique_identifier> <block>cachebuster/cms</block> <placeholder>ARBITRARY_UNIQUE_IDENTIFIER</placeholder> <container>BranchLabs_CacheBuster_Model_Placeholder</container> <cache_lifetime>0</cache_lifetime> </arbitrary_unique_identifier> </placeholders> </config>In the CMS, replace the block types for the blocks you're trying render outside the cache with our newly minted CMS-proof block:
{{block type="cachebuster/cms" block_id="cacheproof"}}
-
Thanks Graham, I'll give it a try and let you know how it went.LDusan– LDusan2014年09月12日 07:01:43 +00:00Commented Sep 12, 2014 at 7:01
-
Did this solve your problem for you @LDusan?Graham– Graham2014年09月29日 22:30:15 +00:00Commented Sep 29, 2014 at 22:30
-
Did not try it yet, I'll let you know :)LDusan– LDusan2014年09月30日 20:44:16 +00:00Commented Sep 30, 2014 at 20:44
-
Graham I think this works, the only drawback is that you would have to change the existing cms block classes if you want them not cached, but regardless it's a good solution. Thanks.LDusan– LDusan2014年10月12日 12:29:25 +00:00Commented Oct 12, 2014 at 12:29
The problem is that Magento core team forgot to cache static blocks and what is not cached individually can't be hole-punched.
So the solution is to fix caching first.
Indeed, the solution would be to change the way caching is done.
Lesti's FPC is doing this right in my souvenir, and it's free. It only lacks the multiple websites support, but it's perfect for 1 website anjd you'll be able to specify the blocks that must be dynamically hole-punched.
I also tried Amasty's FPC, you'll have to pay for it and it's not the perfect caching solution for CE I guess, but it's working well, you can specify caching of blocks / pages or both. You can also set the compression rate of the cached objects and store them in Db / Filesystem (slow) or memcached.
Wish you luck.