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.
Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It only takes a minute to sign up.
Sign up to join this communityShort 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).
$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;
}
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.