-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
There are two types of root elements in layout XML files: <layout> and <page>.
I've been digging throught the source, and finding a few differences, but this isn't giving me a real understanding what they really are for. Could you please explain the differences between <layout> and <page> layout updates?
To demonstrate I've tried to come up with an answer on my own before asking, here is what I've found so far.
The following is not important in regards to the question, please feel free to skip it.
The evaluation of the differences seem to be handled by the layout processor Magento\Core\Model\Layout\Merge. The differences in processing seem to be encapsulated by this class.
The <layout>directive mostly seems to be used in the context of adminhtml pages, price layouts, and page layouts, simply judging by the layout XML file names in which <layout> is used.
There seems to be nothing special about those files otherwise.
Both are collected in the same way and merged together. However, the type of the root element in the file is preserved in the merged XML:
$handleName = basename($file->getFilename(), '.xml');
$tagName = $fileXml->getName() === 'layout' ? 'layout' : 'handle';
$handleAttributes = ' id="' . $handleName . '"' . $this->_renderXmlAttributes($fileXml);
$handleStr = '<' . $tagName . $handleAttributes . '>' . $fileXml->innerXml() . '</' . $tagName . '>';
$layoutStr .= $handleStr;Many of the layout XML files using <layout> start by declaring a root container:
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/layout_generic.xsd">
<container name="root" label="Root">
...
</container>
</layout>
The only <layout> type layout XML files which do not declare a root container and don't inherit one via an <update> declaration seem to be the files
- //base/layout/catalog_product_prices.xml
- Magento/Sales/view/adminhtml/layout/sales_order_create_load_block_customer_grid.xml
- Magento/Store/view/base/layout/ui_components.xml
I would have guessed they are for ajax updates which don't require the root template, but because of these exceptions I've given up on this idea.
When a handle is added to the layout to be processed during a request, both types of handles are treated equaly:
protected function _fetchPackageLayoutUpdates($handle)
{
$layout = $this->getFileLayoutUpdatesXml();
foreach ($layout->xpath("*[self::handle or self::layout][@id='{$handle}']") as $updateXml) {
$this->_fetchRecursiveUpdates($updateXml);
$this->addUpdate($updateXml->innerXml());
}
return true;
}Based on the method Layout\Merge::_fetchRecursiveUpdates() it seemed like <layout> style files are not available for usage with the <update> directive.
protected function _fetchRecursiveUpdates($updateXml)
{
foreach ($updateXml->children() as $child) {
if (strtolower($child->getName()) == 'update' && isset($child['handle'])) {
$this->_merge((string)$child['handle']);
}
}
if (isset($updateXml['layout'])) {
$this->pageLayout = (string)$updateXml['layout'];
}
return $this;
}But this turnes out not to be true, since all the frontend page_layout files include each other using <update>. So both types of layouts are includeable via the <update handle='ID'> directive, even if ID refers to a <layout> type file.
And this is as far as I've got - with no real idea what was the reasoning behind choosing two different root node types.
Thank you for any insight you can provide!