2009年6月16日星期二

[fw-mvc] module specific layout

Hi,

I was looking into adding a layout specific to a certain module. It didn't work out as I planned, so I'm probably missing something. I have a possible solution, but I'm not confident that it's the way to do it.

Let's start by explaining what I did:

1/ I created a admin.phtml and default.phtml in the layouts/scripts directory

2/ I added following code in my application.ini :

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

This loaded the default layout as I expected. So far so good, then I started to play:

resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.layout.layout = default
admin.resources.layout.layout = admin

=> loads the default layout

resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
default.resources.layout.layout = default
admin.resources.layout.layout = admin

=> loads the admin layout (as it was defined last, it will overwrite the default one).

I ended using the second config with a default layout specified in the resource and then specific ones for the modules.

So I gathered that working this way I wasn't going to get anywhere. My second thought was to wirte a custom layout loader (_initLayout), but I realized there was no use, since I need access to the request to find out the current module name.

Then I decided to put it in a plugin. Cool, I have the module name there, I can access the layout, but... mmm... my application config is not readily available (ok, I could probably reload it, but I don't like that approach).

Finally I created a controller action helper, which I initialized from the default bootstrap:

    protected function _initLayoutHelper()
    {
    $this->bootstrap('frontController');
    $layout = Zend_Controller_Action_HelperBroker::addHelper(
    new Amz_Controller_Action_Helper_Layout());
    }

The helper itself is very straight forward (removed the comments to save space, it's very basic stuff):

class Amz_Controller_Action_Helper_LayoutLoader extends Zend_Controller_Action_Helper_Abstract 
{


public function preDispatch() 
{
$bootstrap = $this->getActionController()->getInvokeArg('bootstrap');
$config = $bootstrap->getOptions();
$module = $this->getRequest()->getModuleName();
if (isset($config[$module]['resources']['layout']['layout'])) {
$layoutScript = $config[$module]['resources']['layout']['layout'];
$this->getActionController()
->getHelper('layout')
->setLayout($layoutScript);
}
}


}

I have the layout changing based on module now, but I have some reservations. For instance: will the helper preDispatch be executed once or for every action (i.e. actionstack) ?

Is this the way to move how to do it, or do you guys do it in another way?

Thanks in advance for your feedback,

Wkr
Jeroen

没有评论: