Modify Layout XML
Given a scenario, modify layout: declare/move/remove blocks, containers, include handles, set templates, ordering, and handle cacheability.
Layout XML Overview
Layout Handles & Where Files Live
- Files: In each module under
view/[area]/layout/(e.g.,view/frontend/layout/). - Merge: All layout XML files are merged into a single tree, in module load order from
app/etc/config.php. - Handles: A request resolves to one or more layout handles; controllers and helpers can add handles programmatically.
- Example: Product page handles might include:
default,catalog_product_view,catalog_product_view_type_configurable,catalog_product_view_id_436,catalog_product_view_sku_MJ12. - Tip: To discover handles, set a breakpoint in
\Magento\Framework\View\Result\Layout::addHandle().
Registering a New Layout File
Pick a handle (convert dashes to underscores) and create <handle>.xml at view/[area]/layout/.
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<!-- your directives here -->
</body>
</page>
Common Layout XML Directives
1) Declare a Block
<body>
<referenceContainer name="content">
<block class="Magento\\Cms\\Block\\Block" name="promo.banner" as="promo_banner" after="-"
template="Magento_Cms::block.phtml">
<arguments>
<argument name="block_id" xsi:type="string">promo_banner</argument>
</arguments>
</block>
</referenceContainer>
</body>
- Ordering:
before/afteraccept-(first/last) or a sibling block name. - as vs name: Use
$block->getChildBlock('promo_banner')whenas="promo_banner". Ifasnot set, use thenamevalue.
2) Declare a Container
<body>
<container name="homepage.top" as="homepage_top" label="Homepage Top"
htmlTag="div" htmlClass="homepage-top"/>
</body>
A container renders its child blocks/containers. You can wrap content via htmlTag/htmlClass.
3) referenceContainer
<body>
<referenceContainer name="columns.top">
<block class="Magento\\Cms\\Block\\Block" name="global.notice" after="-">
<arguments>
<argument name="block_id" xsi:type="string">global_notice</argument>
</arguments>
</block>
</referenceContainer>
</body>
4) referenceBlock
<body>
<referenceBlock name="page.main.title">
<action method="setTemplate">
<argument name="template" xsi:type="string">Vendor_Module::page/title.phtml</argument>
</action>
</referenceBlock>
</body>
Use to modify an existing block (template, arguments, actions).
5) Move an Element
<body>
<move element="catalog.compare.sidebar" destination="sidebar.additional" before="-" />
</body>
6) Remove a Block/Container
<body>
<referenceBlock name="report.bugs" remove="true" />
<referenceContainer name="sidebar.main" remove="true" />
</body>
7) Include Another Handle
<body>
<update handle="customer_account"/>
</body>
Includes layout instructions from all customer_account.xml files (commonly used across customer area pages).
8) Non-cacheable Block (Use with Extreme Caution)
<body>
<block class="Vendor\\Module\\Block\\Realtime" name="realtime.block" cacheable="false" />
</body>
cacheable="false" on any block can make the entire page non-cacheable. Only use if the whole page truly must not be cached.
Hands-on Debugging Tips
- Breakpoint in
\Magento\Catalog\Helper\Product\View::initProductLayout()to see product page handles. - Breakpoint in
\Magento\Framework\View\Result\Layout::addHandle()to capture all handles for current request. - Enable template path hints to map blocks to templates quickly (Developer settings).
Further Reading
Exam Tips
- File location:
view/[area]/layout - Directives:
block,container,referenceBlock,referenceContainer,move,remove,update handle - Ordering:
before/after,-for first/last - as vs name:
ascontrolsgetChildBlock()key; if absent, usename - Dynamic handles: by ID/SKU/type for product pages; create specific handle files for targeted changes
- Cache impact:
cacheable="false"can disable FPC for the whole page