Magento – Layout Update XML – Update Handle

layoutmagento-1xml

I'm trying to change the layout handle for specific CMS pages in the back end.

To do this I'm trying to use the following in Design->Page Layout->Layout Update XML

<update handle="store_page" />

My aim is to write a specific layout in the local.xml, pulling in other blocks just for those CMS pages marked as a Store Page.

However when I put this code in it does not update the handle for the CMS page – is anyone able to offer any help on where I may be going wrong or if this is possible? Is there a better way to achieve this?

Best Answer

You can't do that. Specifically, you can't use the <update/> tag in a CMS page's Layout Update XML field.

Magento processes the <update/> nodes when it is initially loading the layout update files, and layout updates from the core_layout_update table. This is done with the fetchRecursiveUpdates function.

#File: app/code/core/Mage/Core/Model/Layout/Update.php

public function fetchPackageLayoutUpdates($handle)
{
    //...
        $this->fetchRecursiveUpdates($updateXml);
    //...

    return true;
}

public function fetchDbLayoutUpdates($handle)
{
    //...
    $this->fetchRecursiveUpdates($updateXml);        
    //...        
}

//...
public function fetchRecursiveUpdates($updateXml)
{
    foreach ($updateXml->children() as $child) {
        if (strtolower($child->getName())=='update' && isset($child['handle'])) {
            $this->merge((string)$child['handle']);
            // Adding merged layout handle to the list of applied hanles
            $this->addHandle((string)$child['handle']);
        }
    }
    return $this;
}

A CMS page, however, is rendered later on via a helper method. The rendering of a CMS page includes this code

#File: app/code/core/Mage/Cms/Helper/Page.php

$action->loadLayoutUpdates();
$layoutUpdate = ($page->getCustomLayoutUpdateXml() && $inRange)
    ? $page->getCustomLayoutUpdateXml() : $page->getLayoutUpdateXml();
$action->getLayout()->getUpdate()->addUpdate($layoutUpdate);
$action->generateLayoutXml()->generateLayoutBlocks();    

The loadLayoutUpdates call is the standard loading of the layout, including the fetchRecursiveUpdates mentioned above.

Then, Magento looks for a custom layout XML update set on the CMS page object

$layoutUpdate = ($page->getCustomLayoutUpdateXml() && $inRange)
    ? $page->getCustomLayoutUpdateXml() : $page->getLayoutUpdateXml();

and adds it directly to the list of updates to apply

$action->getLayout()->getUpdate()->addUpdate($layoutUpdate);

This means the scanning for the update tag is never done.

If I was trying to implement something like this, I'd add a new block in the CMS page's layout update XML, and then add the shared layout items programmatically in the blocks _prepareLayout method. (not sure off the top of my head if that would work w/r/t to timing, but that'd be where I'd start)

Related Topic