I guess every Magento developer worked with template/catalog/product/view.phtml
template. I guess most of them stumbled upon those two blocks:
<?php echo $this->getChildChildHtml('container1', '', true, true) ?>
and
<?php echo $this->getChildChildHtml('container2', '', true, true) ?>
The following article will reveal where do they come from and how they work.
Our research have to start from Magento blocks hierarchy. After the quick look into
catalog.xml one can spot those two block declarations:
<block type="core/template_facade" name="product.info.container1" as="container1">
<action method="setDataByKey">
<key>alias_in_layout</key>
<value>container1</value>
</action>
<action method="setDataByKeyFromRegistry">
<key>options_container</key>
<key_in_registry>product</key_in_registry>
</action>
<action method="append">
<block>product.info.options.wrapper</block>
</action>
<action method="append">
<block>product.info.options.wrapper.bottom</block>
</action>
</block>
and
<block type="core/template_facade" name="product.info.container2" as="container2">
<action method="setDataByKey">
<key>alias_in_layout</key>
<value>container2</value>
</action>
<action method="setDataByKeyFromRegistry">
<key>options_container</key>
<key_in_registry>product</key_in_registry>
</action>
<action method="append">
<block>product.info.options.wrapper</block>
</action>
<action method="append">
<block>product.info.options.wrapper.bottom</block>
</action>
</block>
They are absolutely identical except their names. Let’s take a closer look at their structure.
The first thing that falls into a glance is their type which is core/template_facade. That
means the class of both blocks is Mage_Core_Block_Template_Facade. This is a very
simple class with only three methods. It extends Mage_Core_Block_Template class so
besides of those methods any block with core/template_facade type will act absolutely
same as a block of core/template type. Let’s take a look at those three methods which make
core/template_facade blocks so special.
The first one is setDataByKey:
public function setDataByKey($key, $value)
{
$this->_data[$key] = $value;
}
It just sets the a property with specified $key to a specified $value on a block. Easy as that.
So in our case alias_in_layout property is set to container1 and container2 for each
of two block correspondingly.
The second function is setDataByKeyFromRegistry:
public function setDataByKeyFromRegistry($key, $registryKey)
{
$registryItem = Mage::registry($registryKey);
if (empty($registryItem)) {
return;
}
$value = $registryItem->getData($key);
$this->setDataByKey($key, $value);
}
It gets an object from a registry by $registryKey, gets its property named $key and then sets
it as a property on a block object with same setDataByKey method. So in our case it sets the
options_container property to value which is stored in Mage::registry(‘product’)
->getData(‘options_container’). This value is defined in admin interface for each
product at the Design tab:
So after those instructions in catalog.xml are applied we have two blocks with two properties
set on each. Further in same XML one can find two interesting actions:
<action method="unsetCallChild">
<child>container1</child>
<call>ifEquals</call>
<if>0</if>
<key>alias_in_layout</key>
<key>options_container</key>
</action>
<action method="unsetCallChild">
<child>container2</child>
<call>ifEquals</call>
<if>0</if>
<key>alias_in_layout</key>
<key>options_container</key>
</action>
The only difference is again only the name of a child node. What this action does is it kill
the block that was just created if ifEquals method returns false. And as you may already
guessed this is the third method of Mage_Core_Block_Template_Facade class.
public function ifEquals($conditionKeys)
{
if (!is_array($conditionKeys)) {
$conditionKeys = func_get_args();
}
// evaluate conditions (equality)
if (!empty($conditionKeys)) {
foreach ($conditionKeys as $key) {
if (!isset($this->_data[$key])) {
return false;
}
}
$lastValue = $this->_data[$key];
foreach ($conditionKeys as $key) {
if ($this->_data[$key] !== $lastValue)
{
return false;
}
}
}
return true;
}
What it does, it takes passed conditions and compares them. Number of conditions can be
variable which is served by func_get_args function. In our case alias_in_layout is
compared to options_container.
So what happens is two (or more) blocks are added and then some of them are removed
depending on result of equation. Sounds a little be weird but as long as this functionality is
already there you can use it in cases you want some blocks to be displayed or not depending on
per-product based settings.
Spoiler
Unfortunately this technology has no future. Magento core team possibly evaluated that it is
currently used only in one case which is described in this article and deprecated it in Magento 2.