Zend Layout - A "Smart" layout selector

1.4k views Asked by At

I currently have Zend setup to look for a layout script in each module's view/scripts/layout.phtml file (ie: /application/modules/moduleName/scripts/layout.phtml). This is by setting layout[] to nothing (blank) in the application.ini file (resources.layout[] = )

The issue is that many modules may share the same layout. I don't want to copy the same exact layout into each module that uses it. I know I can set everything to use one layout script by setting a specific path like resources.layout.layoutpath = /layoutPath and everything would use /layoutpath/layout.phtml, and I know I can set individual pages (or whole Controllers, in the init) by using $this->_helper->layout->setLayout('foobaz');

The issue is that some modules will have different layouts, other than the 'standard' one, and I don't want to set it on a by Controller or by Action basis. I want to set it for the entire module, set in one place (or intuitively figured out by code/Zend automatically). Ideally, it would be setup how it is currently, but if a module doesn't have its own layout.phtml, it would use the default module's layout.

So... how do I do it?

3

There are 3 answers

0
SMka On BEST ANSWER

There are several solutions, choose their own strategy

1 extending the action controller

class App_Controller_Action extends Zend_Controller_Action 
{

    public function init()
    {
        parent::init();

        $moduleName = $this->getRequest()->getModuleName();
        $layoutPath = APPLICATION_PATH . '/modules/' . $moduleName . '/layouts';
        if (is_dir($layoutPath)) {
            $this->view->addScriptPath($layoutPath);
        }    
    }
 }

and then do as usual IndexController extends App_Controller_Action ...
if layout file exists in APPLICATION_PATH . '/modules/' . $moduleName . '/layouts' directory - it will ne used instead of default layout

2 you can write frontcontroller plugin

class App_Controller_Plugin_ModuleSwitcher extends Zend_Controller_Plugin_Abstract
 {
     protected $_view = null;

     public function routeShutdown(Zend_Controller_Request_Abstract $request)
     {
         $moduleName = $request->getModuleName();

         Zend_Layout::startMvc();
         $layout = Zend_Layout::getMvcInstance();
         $layout->setLayoutPath(APPLICATION_PATH . '/modules/' . $moduleName . '/layouts')->setLayout($moduleName);

         return $request;
     }
 }

and dont forget to google for another solutions ;)

0
David Snabel-Caunt On

The quickest solution might be to create a symlink to point what would be a module layout file to the default layout. This won't work on Windows and is harder to maintain.

Better, create a method in your Bootstrap to set the layout.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

    public function _initLayoutScript(){
        //ensure layout is setup
        $this->bootstrap(array('layout', 'FrontController'));

        $layout= $this->getResource('layout');

        $front = $this->getResource('FrontController');

        //do something with $layout and $front - set layout script/path etc based on request 
        //You could use file_exists to detect module layout scripts 

    }

}

See http://framework.zend.com/manual/en/zend.application.quick-start.html#zend.application.quick-start.resources for more details.

Finally, you could write your own application resource for use with Zend_Application.

0
Maneesh Singh On

you can set own layout selector in few steps

step 1: make module admin and default.

step 2: create layout folder in each module as admin/layouts/scripts and default/layouts/scripts put into layout.phtml

step 3: delete the layout.phtml file from Application/layouts/scripts.

step 4: make the the Plugin folder inside library and make Plugin.php as

class Plugin_Layout extends Zend_Controller_Plugin_Abstract 
{

   public function preDispatch(Zend_Controller_Request_Abstract $request)

    {
        $layoutPath = APPLICATION_PATH . '/modules/' . $request->getModuleName() . '/layouts/scripts/';
        Zend_Layout::getMvcInstance()->setLayoutPath($layoutPath);
    }
}   

step 5:

open Application/configs/Appication.ini file and edit it as

;resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.layout.layout = "layout"
;register your plugin

autoloaderNamespaces[] = "Plugin"
resources.frontController.plugins[] = "Plugin_Layout"

Step 6:

open bootstrap file Application/Bootstrap put the code inside

protected function _initAutoload()

 {

        $loader = new Zend_Application_Module_Autoloader(array(
                    'namespace' => '',
                    'basePath' => APPLICATION_PATH . '/modules/'
                ));

        return $loader;
    }

    protected function _initPlugins()

{

        $this->bootstrap('frontcontroller');
        $fc = $this->getResource('frontcontroller');
        $fc->registerPlugin(new Plugin_Layout());
}