4.02

Modify Layout XML

Given a scenario, modify layout: declare/move/remove blocks, containers, include handles, set templates, ordering, and handle cacheability.

Why This Matters: Layout XML is Magento's way to connect requests (layout handles) to blocks, containers, and templates. Mastery here lets you add/move/remove UI elements without touching PHP.

Layout XML Overview

mindmap root((Layout XML)) Layout Handles Determined from request Dynamic handles Include handles Files and Merge view/area/layout Merged by module order Override/modify nodes Common Directives block container referenceBlock referenceContainer move remove update Caching cacheable false risk

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/.

app/code/Vendor/Module/view/frontend/layout/catalog_product_view_id_436.xml
<?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/after accept - (first/last) or a sibling block name.
  • as vs name: Use $block->getChildBlock('promo_banner') when as="promo_banner". If as not set, use the name value.

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>
⚠️ Warning: Setting 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: as controls getChildBlock() key; if absent, use name
  • 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