Zend Framework: Using separate layouts per module

Someone was recently asking on ZFTalk about how to use a different layout for each module in your application. Since this is a problem I’ve dealt with in the past and planned on adding to the Galahad FE, I thought I’d quickly write up a tutorial on how to do it:

First, download the Plugin

Put the following class in a library/Galahad/Controller/Plugin/Modularlayout.php file (you’ll probably have to create all those directories and the file).

<?php
/**
* This file is part of the Galahad Framework Extension.
*
* The Galahad Framework Extension is free software: you can redistribute
* it and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* The Galahad Framework Extension is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* General Public License for more details.
*
* @category  Galahad
* @package   Galahad
* @copyright Copyright (c) 2009 Chris Morrell <http://cmorrell.com>
* @license   GPL <http://www.gnu.org/licenses/>
* @version   0.2
*/

/**
* Use separate layout per module
*
* @category   Galahad
* @package    Galahad
* @copyright  Copyright (c) 2009 Chris Morrell <http://cmorrell.com>
* @license    GPL <http://www.gnu.org/licenses/>
*/
class Galahad_Controller_Plugin_Modularlayout extends Zend_Controller_Plugin_Abstract
{
     public function routeShutdown(Zend_Controller_Request_Abstract $request)
     {
          Zend_Layout::getMvcInstance()->setLayout($request->getModuleName());
     }
}

Next, add the Galahad namespace

Update your Bootstrap.php file’s autoloader initialization method (if you don’t have one, add one):

protected function _initAutoloaders()
{
	$this->getApplication()->setAutoloaderNamespaces(array('Galahad_'));
	return $this;
}

Please note: You might need to have other namespaces in there, like My_ or App_ or Default_.

Next, add the Plugin

Update your Bootstrap.php file’s plugin initialization method (if you don’t have one, add one):

protected function _initPlugins()
{
	$this->bootstrap('autoloaders');
	$this->bootstrap('frontController');

	$plugin = new Galahad_Controller_Plugin_Modularlayout();
        $this->frontController->registerPlugin($plugin);
}

And you’re set!

Just make sure you have a layout file in your layouts directory for each module (modulename.phtml).

Related posts:

  1. Zend Framework Bash Completion Script If you use the Zend Framework CLI interface much you...
  2. Zend Framework URI validator & filter For the last couple of months I’ve been incorporating portions...
  3. Installing Zend Server & Zend Framework on OS X This post is mostly a reminder to myself, but I...
  4. PHP Modeling (in Zend Framework) I’ve been thinking a lot about Modeling in a MVC...
  5. Better Zend Framework Documentation If you’ve every tried to navigate the Zend Framework documentation’s...
This entry was posted in Zend Framework and tagged . Bookmark the permalink.
  • http://www.rmauger.co.uk/ Ryan Mauger

    You appear to be using a Front controller Plugin for an action helper!

    please don’t do that, either its one or its the other.

    Yes they are very similar, but they actually should perform two different functions, an action helper should provide something useful to you in an action, or do something such as the viewRenderer, which renders the view for you.

    you should instead simply register the plugin with the Front controller, where it will do pretty much the same thing, and yes it is all semantics, but semantics are for clarity, and your bluring that!

    • http://cmorrell.com Chris Morrell

      Shoot! Good call—fixed.

  • http://twitter.com/newmediahub newmediahub

    Chris Morrell posted: Zend Framework: Using separate layouts per module (http://bit.ly/ADJEV)

    This comment was originally posted on Twitter

  • Axalix

    it is written
    “Put the following class in a library/Galahad/Plugin/Modularlayout.php” but definition starts with
    “class Galahad_Controller_Plugin_Modularlayout”

    I think “/Controller/” is missed in the path.

    • http://cmorrell.com Chris Morrell

      Good point! Fixed.

  • Vlao

    There is an easier and cleaner way:

    protected function _initLayout() {
    Zend_Layout::startMvc();
    }

    The app is now looking in the view folder of the current module for layout.phtml
    If you insist on keeping your layouts in application/layouts and naming them {module}.phtml, your approach is the right one. I prefer my modules completely separate(except for models). It all depends on the application you are building.

    Don’t take this as critisism – just another perspective :)

    • http://cmorrell.com/ Chris Morrell

      Nice! I didn’t know Zend_Layout gave you that option (I don’t see it anywhere in the docs). Good to know.

    • COBAY

      Oh~~
      It’s very simple way.
      me too, same to your perspective

    • Michael Behan

      I can’t seem to get this simple method to work. I put this in my module’s boostrap and have layout.phtml in modules//views but it doesn’t seem to be working. 

    • romainb

      Thank you sooo much!!!

  • Lalith

    Hello

    I have exactly reverse requirement to the one which you have discussed here.

    We have 5 different zend applications built under a single document root,
    Say,
    mainfolder/
    project1/
    zend library and controllers

    project2/
    zend library and controllers
    etc…
    We have set up layouts for each project independently [this is due to the initial req's]

    Now we need to combine or make the project1′s layouts to be common for remaining projects as well, i.e. all the proj2, proj3… should use proj1 layouts.

    How can I accomplish this, please help me

    • http://cmorrell.com/ Chris Morrell

      Just set the layoutPath in your configuration and you should be good to go. Use the same path for each project…

  • Anuradha

    i require separate layout for each controller, how can we do this, for example there are 3 controllers Admin,Accounts,Hr each as different layout

  • http://cmorrell.com Chris Morrell

    All you need to do is change the line:

    Zend_Layout::getMvcInstance()->setLayout($request->getModuleName());

    to something like:

    $layout = $request->getModuleName() . '-' . $request->getControllerName();
    Zend_Layout::getMvcInstance()->setLayout($layout);

    That would load ‘default-index.phtml’ in the default module and index controller.

    CM

  • http://www.webhostings.in/ web hosting in india

    I get it clear idea about Zend framework related information through this blog.Excellent written skills.