Active Module Config V2
June 18, 2010 in Zend Framework
A brand new version of my previously Released Front controller plugin for Zend Framework.
Since the last version of the plugin, I’ve used and cleaned and tried to maintain it. It just ended up unwieldy. So I set about creating this new version. Does exactly the same as the last one, just should be a lot easier to see what it’s doing and when.
So I present to you active Module Config V2
Many thanks to Paul Bouzakis (@paul_eye) for the pointers in ways to make this more readable and concise
<?php
class BinaryKitten_ModuleConfig extends Zend_Controller_Plugin_Abstract
{
/**@var string The Init Name aka initModule */
private $_moduleInitName = '';
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$activeModuleName = $request->getModuleName();
$this->_moduleInitName = $activeModuleName."Init";
$appBootstrap = $this->_getMainBootstrap();
$activeModuleBootstrap = $this->_getActiveBootstrap($appBootstrap, $activeModuleName);
$this->_processApplicationBootstrap($appBootstrap);
if ($activeModuleBootstrap instanceof Zend_Application_Module_Bootstrap) {
$this->_processActiveModuleBootstrap($activeModuleBootstrap);
}
}
/*****************************************************************
* Gets the Main Boostrap Object
*
* @return Zend_Application_Bootstrap_Bootstrap Main Bootstrap
*****************************************************************/
private function _getMainBootstrap()
{
$frontController = Zend_Controller_Front::getInstance();
$bootstrap = $frontController->getParam('bootstrap');
return $bootstrap;
}
/*******************************************************************************
* Gets the Current Active Module's Boostrap Object
*
* @param Zend_Application_Bootstrap_Bootstap $appBootstrap The Main Bootstrap
* @param String $activeModuleName The name to find.
* @return Zend_Application_Module_Bootstrap Active Module Bootstrap
******************************************************************************/
private function _getActiveBootstrap($appBootstrap, $activeModuleName)
{
$moduleList = $appBootstrap->modules;
if (isset($moduleList[$activeModuleName])) {
$activeModule = $moduleList[$activeModuleName];
} else {
$activeModule = $appBootstrap;
}
return $activeModule;
}
/*********************************************************
* Process the methods from within the main bootstrap
* @param Zend_Application_Bootstrap_BootstrapAbstract $appBootstrap The Application Bootstrap;
**********************************************************/
private function _processApplicationBootstrap($appBootstrap)
{
$moduleInitNameLength = strlen($this->_moduleInitName);
$bootstrapMethodNames = get_class_methods($appBootstrap);
foreach ($bootstrapMethodNames as $key=>$method) {
$runMethod = false;
$methodNameLength = strlen($method);
if ($this->_isModuleNameInitMethod($method)) {
$resource = call_user_func(array($appBootstrap, $method));
$resourceName = substr($method, $moduleInitNameLength);
if (!is_null($resource)) {
$this->storeResource($resource, $resourceName, $appBootstrap);
}
}
}
}
/*********************************************************
* Process the methods from within the main bootstrap
* @param Zend_Application_Module_Bootstrap $activeModuleBootstrap The "Active" Modules's Bootstrap;
**********************************************************/
private function _processActiveModuleBootstrap($activeModuleBootstrap)
{
$moduleInitNameLength = strlen($this->_moduleInitName);
$methodNames = get_class_methods($activeModuleBootstrap);
foreach ($methodNames as $key=>$method) {
$runMethod = false;
if ($this->_isActiveInitMethod($method)) {
$resourceName = substr($method, 10);
$runMethod = true;
} elseif ($this->_isModuleNameInitMethod($method)) {
$resourceName = substr($method, $moduleInitNameLength);
$runMethod = true;
}
if ($runMethod) {
$resource = call_user_func(array($activeModuleBootstrap, $method));
if (!is_null($resource)) {
$this->storeResource($resource, $resourceName, $activeModuleBootstrap);
}
}
}
}
/*******************************************************
* Check to see if the method is in style of ModulenameInitXXX
* @param string $method The method name to check
********************************************************/
private function _isModuleNameInitMethod($method)
{
$methodNameLength = strlen($method);
$moduleInitNameLength = strlen($this->_moduleInitName);
$methodNameLonger = ($moduleInitNameLength < $methodNameLength);
$methodNameBeginMatch = $this->_moduleInitName == substr($method, 0, $moduleInitNameLength);
return $methodNameLonger && $methodNameBeginMatch;
}
/*******************************************************
* Check to see if the method is in style of activeInitXXX
* @param string $method The method name to check
********************************************************/
private function _isActiveInitMethod($method)
{
$methodNameLength = strlen($method);
$methodNameLonger = ($methodNameLength > 10);
$methodNameBeginMatch = 'activeInit' === substr($method, 0, 10);
return $methodNameLonger && $methodNameBeginMatch;
}
/***********************************
* Store the resource returned by the function so that it can be "bootstrapped"
* @param misc $resource The Resource to be stored
* @param string $name the name of the resource
* @param Zend_Application_Bootstrap_BootstrapAbstract $bootstrap The Bootstrap against which to store the resource
********************/
private function storeResource($resource, $name, $bootstrap)
{
// Store the resource.. not sure how to do this yet.. if you do let me know!
}
}
[...] erklärt und mit einigen Beispielen aufbereitet. Gibt finde ich einen guten Überblick darüber. Active Module Config V2 | BinaryKitten’s Blog The Concept I wanted to achieve was to have unique Configuration based upon the module that was [...]
This is a good solution for module level resource bootstraping. In fact i like this solution but i found a problem width the implementation above. The functionality must be in the preDispatch plugin method call instead of the routeShutdown method call. This way if the redirector action controller plugin is used or the actionstack action controller plugin is used the BinaryKitten_ModuleConfig front controller plugin will call the module specific resources on every dispatch cycle.
Thanks for the comment, the idea for the plugin is to offer the same functionality as the _init functions inside the bootstrap. This should only happen the once as do the _init functions. If you want to change the code for your own use so that it does something differently, go right ahead.
[...] are some ideas to overcome a part of this problem. One of them is the BinaryKitten’s Active Module Config: The way this works is that it scans the active modules bootstrap for functions starting with [...]
Hi, I was playing around your module autoload .
.
I need some help
Added in the application.ini ,
autoloadernamespaces[] = "BinaryKitten"
and loaded the plugin with the function
public function _initControllerPlugins()
{
$plugin = Zend_Controller_Front::getInstance()->registerPlugin(
new BinaryKitten_ModuleConfig()
);
}
Added in the default Bootstrap with
public function blogInitFunction() {
/* place code here */
echo " Here ";
exit;
}
Added a ModuleName_Bootstrap which extends Zend Bootstrap module . But don’t know why the echo is not coming , but getting 404 .
Is there any thing I missed ?
Thanks
Hi, and thanks for visiting.
1) the 1st thing i see is that the function needs to start with activeInit so your function could be called activeInitBlog()
2) don’t use exit unless you really need to .. it does cause other items to break.
[...] it, I saw that it’s actually doing nothing more than what has already been done by Binary Kitten or Jeroen Keppens (also see the resources mentioned on that page). So a quick test proved that [...]
Hi,
I am really enjoy your script, thank you for it.
But I have a problem in combination with ACL. If the role isn’t allowed to acces admin module, then ModuleConfig loads admin settings because it is setup by url (request) istead options created in Acl check plugin. I found only one solution and it it redirection in Acl check plugin instead of setting request.
Is there any pretty solution to solve this?
Thank you
have you figured out how to store the Resources…it looks like when I do something like this:
public function activeInitRouter() {
$frontController = Model_Controller_Front::getInstance(); // I have my own front controller
$router = $frontController->getRouter();
$config = new Zend_Config_Xml(APPLICATION_PATH . ‘/config/routingbackend.xml’);
$router->addConfig($config, ‘routes’);
$frontController->setRouter($router);
return $router;
}
router is not set correctly.
or am I doing something wrong?
thanks for the great post!! i found it really interesting and it motivated me to set off to solve the storeResource issue. if you’re interested, i re-worked your solution slightly and i think i’ve solved the storeResource issue… you can check it out here: http://offshootinc.com/blog/2011/02/11/modular-bootstrapping-in-zend-framework/ feedback greatly appreciated!
Hi,
thank you for the great job and for both solutions you provided v1 and v2.
However I’m having a very strange problem.
In the first line of the method _getActiveBootstrap when you retrieve the module list, basically, I’m getting a null value in response. I’m not that much experienced in ZF but as far as I understood that lists doesn’t belong to the bootstrap object.
Is it something you faced during your tests and implementation and that you can help me with.
Any suggestion on it will be very appreciated. Thanks a lot again.
Hi again,
In the meanwhile I solved the problem and I think it might be a good idea to share the solution I found. Basically to have the module list populated two things are needed, be sure that each module’s bootstrap extend Zend_Application_Module_Bootstrap and the most important one is to declare in the application.ini the following resource:
resources.modules = On
or
resources.modules =
or
resources.modules[] =
All of them works. This is needed if you want to define your init code within the module bootstrap otherwise you have to use the application one.
I hope this helps.
Cheers,
Marco
Many thanks for sharing.
I looked at the first version u posted before coming here.
I’m thinking about the fact that every module is supose to be self depended. whit this plugin I see som difucultys. When the pluginin is loaded in the module bootstrap u have no way to tell if it’s alredy ben added to the fc.. If I then drop the module in diffrent application all over and dont know if this plugin alredy been added in that application.. well, mayby u see my point?
I could ofc make a check for it before making this plugin run. But I cant be shore the name of the plugin, or the namespace, is the same if someone els wrote that module…
Storing resources:
private function storeResource($resource, $resourceName, $bootstrap)
{
// Store the resource.. not sure how to do this yet.. if you do let me know!
if (null !== $resource) {
$container = $bootstrap->getContainer();
$container->{strtolower($resourceName)} = $resource;
}
}
Then in controller:
$appboot = $this->getInvokeArg(‘bootstrap’);
$module = $appboot->getResource(‘modules’)->default; //or your module name
Then whatever was initialized in module bootstrap through activeInitLog you can access by
$module->getResource(‘log’);
Resources you have initialized in Main application bootstrap you access by
$appboot->getResource(‘resourceName’);