4

I am aware that

  $this->renderLayout(); 

calls the layout. How does this work and what files do i need?

I am receiving no php errors but nothing is produced by the above statement.

Thanks.

3 Answers 3

14

Short answer: Every controller action has an associated layout handle and the handle is a string which relates to the module, the controller and the action for the current request (and is therefore unique to requests which reach that action). When you load and then render the layout in the controller action, all of the blocks for that handle are rendered out to create the page.

Long answer: To expand on the above the layout handle for a particular request is defined as follows. Firstly the relevant controller must be declared as a resource in your modules config.xml, so you would have something like this in config.xml:

<?xml version="1.0"?>
<config>
    ...
    <frontend>
        ...
        <routers>
            <module>
                <use>standard</use>
                <args>
                    <module>NameSpace_Module</module>
                    <frontName>module</frontName>
                </args>
            </module>
        </routers>
        ....
    </frontend>
    ...
</config>

The <routers> section tells Magento that you module has a controller resource and allows the module to accept requests. The <module> node directly under <routers> is what forms the first part of the layout handle, so in this case any layout you define using a handle starting with module_ would cause Magento to load layout which would be specific to this particular module (we of course need to define the controller and action yet).

Now we can add a controller inside the controllers directory of the module, so say we added FooController.php, and this contained the action BarAction():

<?php
class NameSpace_Module_FooController extends Mage_Core_Controller_Front_Action
{
    public function barAction()
    {
        $this->loadLayout();
        $this->renderLayout();
    }
}

You could generate the URL for a request to target barAction() with Mage::getUrl('module/foo/bar');. The controller and action in this controller form the other parts of the layout handle we need that is specific for this request, you simply use the controller and then the action name separated by underscores to create the full layout handle, which in this case would be <module_foo_bar>.

So when rendering the page, all of the declared layout file resources are inspected to see if they contain the layout handle <module_foo_bar> and if it's found the blocks declared within the handle are rendered out in the declared order as as response to the request. To add a layout file for your module which would be such a resource you would do something like the following in config.xml:

<?xml version="1.0"?>
<config>
    ...
    <frontend>
        ...
        <layout>
            <updates>
                <module>
                    <file>module.xml</file>
                </module>
            </updates>
        </layout>
        ....
    </frontend>
    ...
</config>

This would declare a layout file as a resource for your module and then you need to create the file under app/design/frontend/[package]/[theme]/layout/module.xml and it could have contents something like:

<?xml version="1.0"?>
<layout version="0.1.0">
    <module_foo_bar>
        <block type="core/template" name="foo_bar" template="foo/bar.phtml" after="-" parent="content" />
    </module_foo_bar>
</layout>

where <module_foo_bar> is the layout handle. With this, as well as any content rendering under the <default> layout handle (which renders on all pages except things like popups) like header, footer and sidebar, a block of type Mage_Core_Block_Template is instantiated and renders out the content of template foo/bar.phtml (which contains whatever you need it to).

An important note - the highest level block is root and common areas of the page are children of this block (header, footer, left sidebar etc) so if you declare a block with layout name root:

<?xml version="1.0"?>
<layout version="0.1.0">
    <module_foo_bar>
        <block type="core/template" name="root" template="foo/bar.phtml" />
    </module_foo_bar>
</layout>

you will replace the existing root block and you will not see any of the common areas of the page as these blocks are no longer children of root. This can however be useful for a response to something like an AJAX request, or for a popup. A common parent block is content as it is a block of type core/text_list and this special block automatically renders out child blocks according to the layout order defined using before and after attributes when declaring a block. This means you don't need an explicit call to getChildHtml() to output the block content. You do however need this for other block types which aren't, or do not extend off class Mage_Core_Block_Text_List.

You can of course also use your own block rather than core/template and if you need to write custom methods which would then be callable from the template (as the block class includes the template and so you can use $this-> to call block methods from the template) then you would need to do this. Remember to declare blocks as a resource for your module in this case (again in config.xml):

<?xml version="1.0"?>
<config>
    ...
    <global>
        ...
        <blocks>
            ...
            <module>
                <class>NameSpace_Module_Block</class>
            </module>
            ...
        </blocks>
        ....
    </frontend>
    ...
</config>

So in your particular application, you need to run through the above, check what the layout handle is for the request and make sure layout XML is defined for your handle. Also make sure you are not replacing the root block (unless you mean to do this of course).

1
  • This is terrific, I have never known this, this is so clear and makes sense now.
    – Nickool
    Feb 18, 2017 at 19:29
2

$this->renderLayout(); get layout output and process this output to response body and append response

Step1: create get html using $output = $this->getLayout()->getOutput();

Step2: Process response body for current page :

Mage::getSingleton('core/translate_inline')->processResponseBody($output);

Step3: Append html to response body:

$this->getResponse()->appendBody($output); 

Most important: you need load layout using this code at controller

$this->loadLayout();

see

   public function renderLayout($output='')
    {
       .....
        if (''!==$output) {
            $this->getLayout()->addOutputBlock($output);
        }

        ......

        #ob_implicit_flush();
        $this->getLayout()->setDirectOutput(false);

        $output = $this->getLayout()->getOutput();
        Mage::getSingleton('core/translate_inline')->processResponseBody($output);
        $this->getResponse()->appendBody($output);
        Varien_Profiler::stop("$_profilerKey::layout_render");

        return $this;
    }
1
  • Where do I put the layout files and what should I call them?
    – daktau
    Nov 14, 2014 at 14:15
0

I'm assuming you're in your own controller action and right now you're just getting a WSOD.

To just get a normal default layout, you need to load it first. Like this:

$this->loadLayout(); $this->renderLayout();

Adding just this to your controller should already produce output. If you don't have any output you should enable developer mode (if you did not have this enabled already) and look in to the logs in /var/log/.

To get a better sense of how the layout works in Magento I recommend you read this article by Alan Storm. This is probably the best explanation of how the loading and rendering of layout works out there.

3
  • $this->loadLayout(); $this->renderLayout();
    – daktau
    Nov 14, 2014 at 13:38
  • $this->loadLayout(); $this->renderLayout(); Is being used. I would like to know where the controller looks after this statement. eg. What and where are the files I should use? Is it Block or Layout? Thank you.
    – daktau
    Nov 14, 2014 at 13:46
  • Sorry, I misunderstood your question.I will update my answer.
    – Len
    Nov 14, 2014 at 14:25

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.