Recent Posts


The Odd Semantics of Magento 2’s referenceBlock


Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

In Magento 1, it was pretty common to write a bit of layout update XML that looked like the following.

<reference name="head">
    <action method="setLabel">

This XML translates roughly into the following PHP pseudo code

$block = $layout->getBlock('head');     

Or, in plain english, Magento fetches a reference to the already instantiated block object named head, and then calls this block’s setLabel method.

This syntax has survived, mostly, into the Magento 2 era. Although the Magento provided “dev docs” say the syntax is “not recommended“, action methods still work

<referenceBlock name="catalog-search-advanced-link">
    <action method="setLabel">
        <argument name="value" xsi:type="string">Does this Work</argument>

The names have changed a bit — the outer tag is a better named <referenceBlock/>, and the arguments are now an actual <argument name="..."/> node that requires an xsi:type — but the same intent and semantics from M2 are intact.

What’s odd about this is — you can also use <referenceBlock/> to override <argument/> values. The follow code works

<referenceBlock name="catalog-search-advanced-link">
        <argument name="label" xsi:type="string" translate="true">Changing the Label</argument>

This will change the initial value of the label property of the catalog-search-advanced-link block (the <arguments/> node got their name because they set the value of the $data argument passed into the block’s __construct method). While useful, this syntax is odd because the semantics of <reference/> nodes have always been

Get a reference to the already instantiated block object named catalog-search-advanced-link

However, in the <arguments/> case, you’re putting something inside a <referenceBlock/> node that has an impact on the block before it’s instantiated. Having argument nodes here breaks the standard metaphors of the Layout DSL and makes it harder to reason about, and harder to teach to folks new to the platform. Also, with the reference metaphor broken, it’s not clear how different modules trying to set arguments on the same block will resolve their differences. Is it just an extra merge with the original <block/>? Or is there more custom logic at play?

I recall early in Magento 2’s development cycle an architect mentioned the changes and recommendations for the Layout DSL were an attempt to make the language more declarative (vs. imperative). A declarative layout DSL would have been a pretty neat thing. Unfortunately, a declarative feature or two sitting along side mostly imperative code only serves to confuse things, and make the technical moat around access to Magento development larger, not smaller.

Copyright © Alan Storm 1975 – 2022 All Rights Reserved

Originally Posted: 27th December 2017