Zend Framework: module specific layout

In this article I will show you how set up module specific layouts. Many people find it confusing that module resources like layouts are always loaded, regardless of the module requested. The reason for this is that at the time of bootstrap, the request is not yet determined and the application does not know what module was requested. To set up resources like layouts, databases, translations etc. for specific modules ONLY when that module is requested, your best bet is a front controller plugin or action helper.

Usage example

Default layout settings in application.ini:

resources.layout.layout = "default"
resources.layout.layoutPath = APPLICATION_PATH "/views/layouts"

Then, if you use my ModuleSetup resource as described in module config, you can set the module layout options in the module.ini for that module:

resources.layout.layout = "modulename_default"
 
; this layoutpath is relative to the directory of the module itself
; in this case: application/modules/modulename/views/layouts
resources.layout.layoutPath = "views/layouts"

or, you can set the module config in your application.ini normally, as described in the Zend Framework reference:

modulename.resources.layout.layout = "modulename_default"
 
; this layoutpath is relative to the directory of the module itself
; in this case: application/modules/modulename/views/layouts
modulename.resources.layout.layoutPath = "views/layouts"

* note: you can set all options for module layouts sources the same way as for the application layout resource. If you don’t specify a different layoutPath, the standard path is used

The result is that when the module ‘modulename’ is requested, the layout ‘modulename_default.phtml’ in the directory ‘application/modules/modulename/views/layouts’ is used. Otherwise, the main layout is used.

Code

class Rexus_Controller_Plugin_RequestedModuleLayoutLoader
    extends Zend_Controller_plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $config     = Zend_Controller_Front::getInstance()
                            ->getParam('bootstrap')->getOptions();
        $moduleName = $request->getModuleName();
 
        if (isset($config[$moduleName]['resources']['layout']['layout'])) {
            $layoutScript = $config[$moduleName]['resources']['layout']['layout'];
            Zend_Layout::getMvcInstance()->setLayout($layoutScript);
        }
 
        if (isset($config[$moduleName]['resources']['layout']['layoutPath'])) {
            $layoutPath = $config[$moduleName]['resources']['layout']['layoutPath'];
            $moduleDir = Zend_Controller_Front::getInstance()->getModuleDirectory();
            Zend_Layout::getMvcInstance()->setLayoutPath(
                $moduleDir. DIRECTORY_SEPARATOR .$layoutPath
            );
        }
    }
}

To use this, drop the class above in your library and set the following in your application.ini:

resources.frontController.plugins.layoutloader = Rexus_Controller_Plugin_RequestedModuleLayoutLoader

If you want to know more about handling other types of resources with modules, check my post about module translation sources

15 thoughts on “Zend Framework: module specific layout

  1. Hi

    Just needed to add:

    public function init() {
    Zend_Layout::startMvc();
    }

    to your class to make it work. I guess it can be some other issue, anyway it could be useful to post this.

    Thanks, great work with the modules thing for Zend Framework

  2. Pingback: Zend Framework , wamp and bootstrap! « {"sintax":["Flex","Flash","AS3","etc"]}

  3. I ended up put this in the module.ini:

    resources.frontController.plugins.layoutloader = Rexus_Controller_Plugin_RequestedModuleLayoutLoader

    and then it finally worked.

  4. We would really profit a lot if you could post some Source Code from your implementations.

    I cannot get it running having a unique layout for each module, it is always refering to the main module.

  5. Hi,

    I was pulling the last few hairs out of my head when I stumbled upon this code along with the Module Config one.

    I really can’t thank you enough … Your’re awsome

    I’d like to suggest resetting the options of all the resources, any thoughts about that?

  6. Pingback: Darryl E. Clarke » Blog Archive » Multiple Paths for Zend_Layout (Modules Based Layouts)

  7. Hi,

    Thank you for your helpful articles.

    To get my scripts work fine, I needed to change some parts of the example.
    And I hope my comment here would help those who are struggling.

    I use application.ini for module configuration, and its settings are as follows:

    ;default module
    default.resources.layout.layout = “layout”
    default.resources.layout.layoutPath = APPLICATION_PATH “/layouts/scripts/”
    ^^^^^^^^
    ;admin module
    admin.resources.layout.layout = “adminlayout”
    admin.resources.layout.layoutPath = APPLICATION_PATH “/modules/admin/layouts/scripts/”

    And I edited some lines of your LayoutLoader script as follows:

    //$moduleDir = Zend_Controller_Front::getInstance()->getModuleDirectory();
    Zend_Layout::getMvcInstance()->setLayoutPath($layoutPath);

    Since the layoutPaths of my configuration are defined with absolute paths, I needed to change the parameter for the setLayoutPath() method.

    Best wishes.

  8. Hi I’m newbie in zend so please tell me where exactly put the class with which file name and path I need it.
    thanks

  9. 1) thanx to nicolas, use his piece of code with init() if you get an error like this: Call to undefined method Rexus_Controller_Plugin_RequestedModuleLayoutLoader::init()

    2) first i was getting an error that said it couldn’t find the (undefined) class Rexus_Controller_Plugin_RequestedModuleLayoutLoader so i have turned that simple on line configuration from application.ini into three ugly lines (that’s bad, isn’t it?:( ):

    pluginPaths.Rexus_Controller_Plugin = “Rexus/Controller/Plugin”
    resources.frontController.plugins.requestedmodulelayoutloader = Rexus_Controller_Plugin_RequestedModuleLayoutLoader
    resources.requestedmodulelayoutloader = ”

    hope this helps…

    3) important notice @Behrang: if you were familiar with this blog and added Matthijs on you favorite list of blogs you would have known now that all code of his should reside in library/Rexus/… so that code should go into library/Rexus/Controller/Plugin/RequestedModuleLayoutLoader.php – also don’t forget to add that init() method

    4) thanks alot for this tutorial!!! you’re doing a great job :)

    • In part 2 you put three lines…

      pluginPaths.Rexus_Controller_Plugin = “Rexus/Controller/Plugin”
      resources.frontController.plugins.requestedmodulelayoutloader = Rexus_Controller_Plugin_RequestedModuleLayoutLoader
      resources.requestedmodulelayoutloader = ”

      (The 3rd line not really coming out anyways, the better way to add the library is:

      autoloadernamespaces.rexus = “Rexus_”
      resources.frontController.plugins.requestedmodulelayoutloader = Rexus_Controller_Plugin_RequestedModuleLayoutLoader

  10. Hi! I need help with implementing this plugin to Zend Framework 1.11.
    I did exactly what is said here, and I did some little corrections on the INI file (added autoloading
    namespace because of exception shouting ‘cant find that plugin’). Now I am stuck on:

    Fatal error: Call to a member function getOptions() on a non-object in /home/apsik/www/rdp/library/Rexus/RequestedModuleLayoutLoader.php on line 16

    this line and its neighborhood looks like

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
    $config = Zend_Controller_Front::getInstance()
    ->getParam(‘bootstrap’)->getOptions();
    $moduleName = $request->getModuleName();

    so this error refers to Zend_Controller_Front::getInstance()->getParam(‘bootstrap’)->getOptions();

    Please HELP! \o/

  11. I’ve followed your instructions for both the modular config and the module specific layout and all I’m getting is “Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 261904 bytes) in path\to\localhost\site\library\Zend\Config\Ini.php on line 251″

    Sounds to me like a continuous loop somewhere. Any ideas how I might be able to resolve this?

    Many thanks

  12. Pingback: Zend Framework: module specific frontcontroller plugins | vandenbos.org

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>