4

I have seen cache.xml in etc folder in some modules.What exactly does cache.xml and what exactly purpose of cache.xml and its xml code ?

I have seen some code in cache.xml like this

<config>
    <placeholders>
        <my_placeholder_identifier>
            <block>mycompany_mymodule/blockname</block>
            <placeholder>MY_PLACEHOLDER_NAME</placeholder>
            <container>Mycompany_Mymodule_Model_Container_Blockname</container>
             <cache_life>0</cache_life>
             <cache_lifetime>0</cache_lifetime>
        </my_placeholder_identifier>
    </placeholders>
</config>

What this above code in etc/cache.xml ?

Above code works for only magento enterprise edition ?

This code works for only full page cache ?

Why we write block path and model path ? and What I have to write in block and model path ?

7

Yes, cache.xml will only be picked by Enterprise edition Full Page Cache. Though I heard there might be compatible implementations out in the wild.

In <block> you write block types (same as in layout) to make them be processed in a special way when cache is enabled. And you need to create a container class and reference it in <container> - it must at very least implement 2 methods: _getCacheId and _renderBlock method.

Briefly, when full page cache is enabled, by default all page is cached. This isn't acceptable for dynamic or user-specific blocks such as minicart, so Full Page Cache (FPC) can punch-hole those blocks for rendering separately.

Before saving page to cache, all blocks that are registered in cache.xml get replaced with their definition marker. When loading fully cached page, all definitions are parsed, blocks are rendered individually and inserted into content. Rendering happens in your <container> applyWithoutApp, then applyInApp if necessary. This is where you place special custom logic.

More detailed - save to cache:

When first rendering page that is not cached, FPC observes event core_block_abstract_to_html_after for all blocks, and if meets a block that is defined in someone's cache.xml under <block> tag, it does 3 things:

  • saves rendered dynamic blocks to cache - allows them to have own cache lifetime and tags. To be loaded from cache in applyWihoutApp
  • wraps it in start/end tags <!--{MY_PLACEHOLDER_NAME_hash}-->rendered block content<!--/{MY_PLACEHOLDER_NAME_hash}--> - this is needed to completely extract them later

Before final response, in event controller_front_send_response_before, resulting page is cached. But first it greps all placeholders by pattern /<!--\{(.*?)\}-->/i and replaces them with their placeholder definition string for restoring them next time page loads.

definition example:

<!--{MY_PLACEHOLDER_NAME
  container="Mycompany_Mymodule_Model_Cache_Container_Dynamic"
  block="Convert_Cert_Block_Dynamic"
  cache_id="c1edfcf3858cef371e7eca712834ec17a50c6443" <-- block.getCacheKey()
  template="mycompany/mymodule/dynamic.phtml"
  something="yes" xyz="33"  <-- extra data from original block.getCacheKeyInfo
}-->

Load from cache:

Next time cached page is requested, FPC loads cache and needs to render placeholders instead of their markers (remember, dynamic content is cut out before saving to cache). If greps again all <!--{}--> definitions and renders all of them. <container> class is responsible for rendering and inserting rendered content into result content html.

It is a 2-step process:

  • All placeholders are asked render without Magento $app environment. container.applyWithoutApp(). By default dynamic block content tries to load from cache. If all blocks returned true, no need to instantiate full Magento instance, content is returned to browser immediately.
  • If any placeholder failed to apply without app (returning false), request route info is replaced with path pagecache/request/process. When magento calls this action, this means Magento $app is now available, all left placeholders are rendered using container.applyInApp(). By default this methods calls container._renderBlock() - here you must render your block.

This is an example to make some block completely dynamic without any caching:

class Mycompany_Mymodel_Model_Cache_Container_Dynamic extends Enterprise_PageCache_Model_Container_Abstract
{
    protected function _getCacheId()
    {
        // REQUIRED for dynamic blocks to work
        return $this->_placeholder->getAttribute('cache_id');
    }

    public function applyWithoutApp(&$content)
    {
        // by default will attempt to load block from cache.
        return false; // always dynamic
    }

    protected function _renderBlock()
    {
        // will call layout.createBlock() using type and template from placeholder definition
        $block = $this->_getPlaceHolderBlock();


        // not absolutely necessary
        $block->setNameInLayout($this->_placeholder->getAttribute('name'));

        return $block->toHtml();
    }
}

There can be difficulties when referencing other blocks, e.g. parent, because they won't be created in cached version, or when you need some value from Mage::registry(). This is why you need your <container> class to work this out for your dynamic block.

  • Thanks Roman for quick and deep answer.Again thank you very much – Niraj Patel Aug 27 '16 at 20:43

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.