Zend Framework: module specific frontcontroller plugins

Here is another situation I have run into while trying to build a modular application: sometimes you need to run a frontcontroller plugin ONLY when a specific module is requested. An example could be authentication. Say I have a public site and an admin section. The most obvious solution is to enable the authentication plugin only when the admin section is requested. This is something that is not possible with Zend_Application and the frontcontroller resource. So, as I did for loading module specific layouts, I wrote a frontcontroller plugin for registering module specific frontcontroller plugins: the Rexus_Controller_Plugin_RequestedModulePluginLoader. It works together with a Zend_Application resource called Rexus_Application_Resource_Moduleplugins. Let’s get started.

Usage Example

First we load the frontcontroller plugin Rexus_Controller_Plugin_RequestedModulePluginLoader in the main application.ini:

resources.frontController.plugins.pluginloader = Rexus_Controller_Plugin_RequestedModulePluginLoader;

Then we use the Zend_Application resource Rexus_Application_Resource_Moduleplugins in our config file to load the the authentication plugin only for our module.
If you use my ModuleSetup resource as described in module config, you can set the module plugin options in the module.ini for that module :

resources.moduleplugins.auth = "Rexus_Controller_Plugin_Authentication"

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

modulename.resources.moduleplugins.auth = "Rexus_Controller_Plugin_Authentication"

The result is that the frontcontroller plugin Rexus_Controller_Plugin_Authentication is only loaded if the module ‘modulename’ is requested.

Code

class Rexus_Controller_Plugin_RequestedModulePluginLoader 
    extends Zend_Controller_Plugin_Abstract
{
    protected $_modulePlugins = array();
 
    public function registerFrontControllerPlugin($module, $pluginName)
    {
        if (array_key_exists($module, $this->_modulePlugins) 
                        && is_array($this->_modulePlugins[$module])) {
 
            array_push($this->_modulePlugins[$module], $pluginName);
        } else {
            $this->_modulePlugins[$module] = array($pluginName);
        }
    }
 
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        if (isset($this->_modulePlugins[$request->getModuleName()])) {
            $frontController = Zend_Controller_Front::getInstance();
            foreach ($this->_modulePlugins[$request->getModuleName()] as $pluginName) {
                $frontController->registerPlugin( new $pluginName);
            }
        }
    }
}

Just drop this class in your library and register the plugin with the frontcontroller as shown above to use it.

Note that this plugin does its work on routeShutdown. On routShutDown is the earliest hook in the dispatch loop where the request has been parsed and routed. This is important because all plugins we register with this plugin can subsequently only be registered with the frontcontroller as early as the next step after the one on which this plugin is executed.

Next we need the code for the Zend_Application resource Rexus_Application_Resource_Moduleplugins:

class Rexus_Application_Resource_Moduleplugins 
    extends Zend_Application_Resource_ResourceAbstract
{
    public function init()
    {
        $bootstrap = $this->getBootstrap();
        $bootstrap->bootstrap('frontcontroller');
        $front = $bootstrap->getResource('frontcontroller');
        $pluginLoader = $front->getPlugin('Rexus_Controller_Plugin_RequestedModulePluginLoader');
        $options = $this->getOptions();
 
        foreach ($options as $pluginName) {
            $pluginLoader->registerFrontControllerPlugin(
                strtolower($this->getBootstrap()->getModuleName()), $pluginName);
        } 
    }
}

5 Comments

  1. ade says:

    Where is the class “Rexus_Controller_Plugin_Authentication” ? Thanks.

  2. leon says:

    I’m not too sure how you load Rexus_Application_Resource_Moduleplugins, is it in the application.ini?

  3. leon says:

    Just in case, this is how I got around the module specific loading of an authentication mechanism:

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
    protected function _initAuth()
    {
    $frontController = $this->bootstrap(‘frontController’)->frontController;
    $frontController->registerPlugin(new Cantah_Controller_Plugin_Auth(array(‘modules’=>’admin’)));
    }

    Then in the preDispatch of the Cantah_Controller_Plugin_Auth plugin I check if a module is set, and if the module is admin, do the appropriate Zend_Auth checking.

  4. musca ilie says:

    i subscribe to what leon said.. how do I load the Rexus_Application_Resource_Moduleplugins ?

    apache crashes if i use only the code above.. something is missing

  5. musca ilie says:

    ok, i managed to load the moduleplugins resource.

    using ZF 1.9 the class Rexus_Application_Resource_Moduleplugins doesn’t work at all..

    php crashes because of this line $this->getBootstrap()->getModuleName()

Leave a Reply