Question

How to conditionally add a block (depending on the configuration in the admin panel) in Magento's layout XML?

We can check if config is true on actions. In the example below, if sample/config/show_toplinks config from the admin panel (in System->Configuration) is true, then the template file links.phtml will be used to render Top Links. If sample/config/show_toplinks is false, then the default template will be used.

<reference name="top.links">
    <action method="setTemplate" ifconfig="sample/config/show_toplinks">
        <template>page/template/links.phtml</template>
    </action>
</reference>

I found this workaround somewhere in the web. We can set an empty template as a default template for Top Links, like this:

<reference name="top.links">
    <action method="setTemplate" ifconfig="sample/config/show_toplinks">
        <template>page/template/links.phtml</template>
    </action>

    <!-- OR set completely empty template -->
    <action method="setTemplate">
        <template>page/template/empty_template_for_links.phtml</template>
    </action>
</reference>

In this case, if sample/config/show_toplinks is true, then the template links.phtml will be used and Top Links will be displayed. but if sample/config/show_toplinks is false, then the empty_template_for_links.phtml template will be used and that template is completely empty, so it doesn't return any HTML and the Top Links will not be visible.

  1. Is there any other way to conditionally show or hide blocks depending on the configuration in the admin panel?
  2. Is this workaround safe?
  3. Can this cause any unexpected errors?

EDIT:

Based on all answers I think that Rick Kuipers' solution looks the most convenient for my case. But I have another related question:

    <block type="core/template" name="my_block" template="my/block.phtml" />
    <!-- ...add more blocks here -->

    <reference name="footer">
        <action method="append" ifconfig="sample/config/show_toplinks">
            <block>my_block</block>
        </action>
        <!-- ...append more blocks here -->
    </reference>

If I have many blocks to add like this (using append method and ifconfig), let's say 50, does it affect the performance? Only some of the blocks will be really displayed (that depends on the user's setting in the System -> Config), but I need to add all those blocks before I conditionally append them inside <reference name="footer">...</reference>.

Does Magento instantly process all blocks added like this?

    <block type="core/template" name="my_block" template="my/block.phtml" />

Or blocks are processed only if they have to be finally displayed in the template? So will Magento have to process all my 50 blocks despite the fact that only some of those blocks need to be displayed?

Was it helpful?

Solution

I would like to add my option as opposed to benmarks' answer.

My approach is to use the append action:

    <block type="core/template" name="my_block" template="my/block.phtml" />
    <reference name="head">
        <action method="append" ifconfig="myblock/general/enabled"><block>my_block</block></action>
    </reference>

OTHER TIPS

By using the _template property to hide output is a novel approach. I would prefer to reverse values on the config option so that Yes = 0 (perhaps a custom source model) and call unsetChild on the parent head block:

<reference name="head">
    <action method="unsetChild" ifconfig="sample/config/show_toplinks">
       <child>topLinks</child>
    </action>
</reference>

As to your questions:

  1. My method just expands upon yours

  2. I can't see why it wouldn't be

  3. Again, your code's pretty safe behind methods that won't cause exceptions (getStoreConfig for one, will just return falsy values, so your conditional handle won't be added) but you will get an exception if the empty template file doesn't exist. Use a self-closing tag to pass an empty value (e.g. <template />)

If I was developing this, I would extend your solution to include an observer which checks the config and conditionally adds a handle to your layout. Then, in your layout file you can set both actions inside different handles-default and show_toplinks

<config>
  <global>
    <!-- stuff -->
    <events>
      <controller_action_layout_load_before>
        <observers>
          <my_module_add_handle>
            <class>my_module/Observer</class>
            <method>addHandle</method>
          </my_module_add_handle>
        </observers>
      </controller_action_layout_load_before>
    </events>
    <!-- other stuff -->
  </global>
</config>

And then in your Observer Model...

public function addHandle(Varien_Event_Observer $observer)
{
    if (Mage::getStoreConfig('sample/config/toplinks') {
        $observer->getEvent()->getLayout()->getUpdate()
            ->addHandle('show_toplinks');
    }
}

Aaaand finally in your layout:

<default>
  <reference name="top.links">
     <!-- yup -->
  </reference>
</default>

<show_toplinks>
  <reference name="top.links">
     <!-- another yup -->
  </reference>
</show_toplinks>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top