:::: MENU ::::

Magento Certification: Rendering Blocks (part 7)

4.25 avg. rating (82% score) - 8 votes

Explain different mechanisms for disabling block output

In which ways can block output be disabled in Magento?

There are some ways you can disable the block output in Magento.

Remove a block from the layout in Magento

In the layout files, you can set a remove node to disable the block. This will not only disable the output but also makes the block will not be instantiated. In the layout you can set something like:

<reference name="left">
  <remove name="left.permanent.callout" />
  <remove name="tags_popular" />
  <remove name="left.newsletter" />
</reference>

This will remove from the left column the three blocks, so in fact the output for them are disabled.

Remove entire module output in Magento

In the admin area you can go to System => Configuration => Advanced and disable a particular module output.

Note this will disable ouput for all blocks in that module, and not only a particular block.

Override block _toHtml or _afterToHtml methods

In your class module, find any of the following methods and set a return statement at the beginning. If not existing, create the method, that will override the one in Mage_Core_Block_Abstract:

protected function _toHtml() {
  return '';
}
protected function _afterToHtml($html)
  return '';
}

Capture and override with an event observer

This is probably not the best option as it could have some performing issues, but you could capture the output from any block by declaring an observer. For this to work you will need to declare your own module, and then in the XML put the following lines:

...
<global>
...
    <events>
        <core_block_abstract_to_html_after>
            <observers>
                <some_identifyer_of_the_observer>
                    <class>module/observer</class>
                    <method>someMethodName</method>
                </some_identifyer_of_the_observer>
            </observers>
        </core_block_abstract_to_html_after>
    </events>
...
</global>
...

Then, declare a Model with the same name (in this case, Observer.php) and put the followgin method:

class Yournamespace_Yourmodule_Model_Observer {

   public function someMethodName(Varien_Event_Observer $observer) {
      $block = $observer->getBlock();
      if ($block->getName() == 'name-of-the-block') {
         $html = $transport->getHtml();
         $html = '';
         $transport->setHtml($html);
      }
   }
}

Which method can be overridden to control block output?

As said before, you can override some of the following methdos:

  • protected function _toHtml() {}
  • protected function _afterToHtml($html) {}

Describe how a typical block is rendered

Which class performs rendering of the template?

The rendering of the block is done by Mage_Core_Block_Abstract, in the final method toHtml().

This method makes three calls that performs rendering and these methods are overriden but each subclass:

final public function toHtml() {
  . . .
  $this->_beforeToHtml();
  $html = $this->_toHtml();
  $this->_saveCache($html);
  . . .
}

In particular, the call to _toHtml is overriden by the common blocks in Magento:

  • Mage_Core_Block_Template
  • Mage_Core_Block_Text
  • Mage_Core_Block_Text_List

Which classes are responsible for figuring out the absolute path for including the template file?

As we can see in Mage_Core_Block_Template, there is a method that looks for the template file. For this to be done it calls the main design class in Magento: Mage_Core_Model_Design

public function getTemplateFile()
{
    $params = array('_relative'=>true);
    $area = $this->getArea();
    if ($area) {
        $params['_area'] = $area;
    }
    $templateName = Mage::getDesign()->getTemplateFilename($this->getTemplate(), $params);
    return $templateName;
}

If we look at the getTemplateFilename method we will see it simply calls to another method in the same class, getFilename:

public function getFilename($file, array $params)
{
    Varien_Profiler::start(__METHOD__);
    $this->updateParamDefaults($params);
    $result = $this->_fallback($file, $params, array(
        array(),
        array('_theme' => $this->getFallbackTheme()),
        array('_theme' => self::DEFAULT_THEME),
    ));
    Varien_Profiler::stop(__METHOD__);
    return $result;
}

This method performs the fallback to find the proper file path, looking into current theme, default theme and finally in base package/theme.

In which method are templates rendered?

Templates are rendered in Mage_Core_Block_Template, in the following method:

public function fetchView($fileName)
{
    . . .
 
    // Templates can be output directly to the browser or its content added to
    // the response which at the end of the process is sent to the browser
    // in one piece. In most cases, it will be stored in the response and
    // Magento will send it at the end of the request processing
    $do = $this->getDirectOutput();
    if (!$do) {
        ob_start();
    }
 
    . . .
 
    // This part includes the template file directly, so it's result is output 
    // directly or captured to a variable (see ob_start and ob_get_clean calls)
    // The template file path is generated by realpath...
    $includeFilePath = realpath($this->_viewDir . DS . $fileName);
    if (strpos($includeFilePath, realpath($this->_viewDir)) === 0 || $this->_getAllowSymlinks()) {
        include $includeFilePath;
    } else {
        Mage::log('Not valid template file:'.$fileName, Zend_Log::CRIT, null, null, true);
    }
      
    . . .
 
    // Finally the generated output by the template, is captured or output.
    if (!$do) {
        $html = ob_get_clean();
    } else {
        $html = '';
    }
    . . .
}



One Comment

  • Responder Kim |

    «In which method are templates rendered?»

    The fetchView() Method includes the template File. The Layout itself is renderd before, when the design_package Class is instanciated:
    1. core/design_package -> get Theme File location
    2. core/layout -> create instances of block Models from XML
    3. For each Block, the fetchview Method of each Block is called by the controller Instance -> renderView()

Hey! Qué opinas sobre el artículo?