34

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?

0

3 Answers 3

32

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>
7
  • 1
    This can apply in certain cases (and was an initial thought of mine), however in this case the block in question (top.links) is invoked by default from the core.
    – benmarks
    Commented May 4, 2013 at 12:55
  • @benmarks ah you mean for the sake of having it modular? Then your approach would be the best approach in this case. Commented May 4, 2013 at 13:30
  • 1
    @RickKuipers 1. Can you clarify how this "append" method works? Will it move my_block inside "head", or will it add another copy of that block inside "head" and the first copy will be still displayed somewhere else (as the block was already added before <reference name="head">)? 2. In which PHP file can I find all those layout methods like "append" or "unsetChild"?
    – zitix
    Commented May 4, 2013 at 14:08
  • 1
    @zitix If the block's definition is in the <reference name="root"> (or any other non core/text_list block) then it won't be automatically displayed unless it's being called by getChildHtml(). It won't move the block, it will be a copy so you can append it multiple times. <action> calls a method in the block. So it depends on which block we're talking about. You can find a few standard ones in Mage_Core_Block_Abstract. But any method owned by the block can be called using <action>. Commented May 4, 2013 at 14:15
  • @RickKuipers And how does this method affect performance? (I edited my question) Block needs to be added <block type="core/template" name="my_block" template="my/block.phtml" /> even if it will not be finally displayed.
    – zitix
    Commented May 4, 2013 at 19:26
15

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>
2
  • 1
    Thank you, this is very good but it requires inverting all the config fields in the System -> Config. I would need to change: Top Links: [enable/disable] to something like Hide Top Links: [Yes/No].
    – zitix
    Commented May 4, 2013 at 19:12
  • 1
    Source models for system config are incredibly easy, and this path is much less complicated than adding a custom layout update handle via observer.
    – benmarks
    Commented May 4, 2013 at 22:50
13

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>
1
  • Thank you, I didn't know this, I will for sure use this method in the future. But for what I need to do now, it requires too much additional code.
    – zitix
    Commented May 4, 2013 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.