Layout That Survives an Upgrade

Target names, keep the override small, and never copy a core layout file wholesale.

Syntax<theme_dir>/<Vendor>_<Module>/layout/<handle>.xml — merged; layout/override/base/<handle>.xml — replaced

Layout merging gives you two ways to change a page: add a small file that merges with the core one, or replace the core file outright. The first survives upgrades. The second freezes a snapshot of the 2.4.9 tree in your project.

Target names, not positions

Point at a container or block name: product.info.main, content.aside, sidebar.main. Those names change rarely, and a change is a documented backward-incompatible change. Position relative to a named sibling with after="product.price.tier" rather than assuming your block is last, and avoid entity handles such as catalog_product_view_id_42, whose id differs between environments.

Keep the override small

One file per handle, holding only the lines that change. A file with three directives is easy to read in a conflict and easy to delete when the feature goes. A same-named file in your module or theme is merged, so you never need to restate the parts you are happy with.

Why copying a core file hurts

A copy under layout/override/base/ replaces the original. When 2.4.10 adds a block to that file, your copy silently drops it, and the missing block looks like a Magento bug rather than your change. Replace a file only when merging genuinely cannot express the change.

After an upgrade

Run bin/magento setup:upgrade, then bin/magento setup:di:compile for production mode, then bin/magento cache:flush, and reload the pages you changed with template hints on.

Example

Example · xml
<!-- app/design/frontend/Acme/storefront/Magento_Catalog/layout/catalog_product_view.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="product.info.mailto" remove="true"/>
        <move element="product.info.review"
              destination="product.info.main"
              after="product.price.tier"/>
    </body>
</page>

When to use it

  • Keep a product-page change working across a 2.4.x upgrade.
  • Clean up an inherited theme that copied core layout files.
  • Make your module's layout changes win over another module's.
  • Review a colleague's layout override before it is merged.

More examples

The copy that breaks on the next upgrade

This is the shape to avoid. The override replaces the core file, so every block the core adds in a later release is missing on this theme and nothing reports it. If you have inherited one, diff it against the vendor file, keep only the lines that differ, and move them into a merged file with the same name but no override/base in the path.

Example · xml
<!-- app/design/frontend/Acme/storefront/Magento_Catalog/layout/override/base/catalog_product_view.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <!-- 200 lines pasted from vendor/magento/module-catalog, with two edits -->
        <referenceContainer name="content">
            <container name="product.info.main" htmlTag="div" htmlClass="product-info-main">
                <!-- ... -->
            </container>
        </referenceContainer>
    </body>
</page>

Controlling which file merges last

Module layout files merge in the order recorded in app/etc/config.php, which is derived from these sequence entries. Declaring the modules you change makes your file merge after theirs, which is what overriding an argument or cancelling a removal depends on. Run bin/magento setup:upgrade after editing module.xml so the new order is written, then bin/magento cache:flush.

Example · xml
<!-- app/code/Acme/Delivery/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Acme_Delivery">
        <sequence>
            <module name="Magento_Catalog"/>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

Checking the change after an upgrade

An upgrade can rename or move a core element, and your layout file then targets a name that no longer exists: no error, just a missing block. Grepping the vendor layout files for every name your overrides reference turns that into a two-minute check. Do it before the release, with the storefront pages you changed open.

Example · bash
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush

# confirm your names still exist upstream
grep -rn 'name="product.info.main"' vendor/magento/module-catalog/view/frontend/layout
grep -rn 'name="product.price.final"' vendor/magento/module-catalog/view/frontend/layout

Discussion

  • Be the first to comment on this lesson.