Compared to Yii, I was surprised that modules in Zend are very hard to implement. What I wanted was a way to initialize my resources using a module specific configuration file; and a way to run code specific for a module (i.e. add actions to an action stack). Thanks to guidelines from Matthew[1] and module configurators from Padraic[2]: I implemented my own module configurator.
Here is my directory structure:
./ application/ configs/ application.ini layouts/ modules/ default/ configs/ module.ini controllers/ forms/ layouts/ library/ Configurator/ Layout.php models/ views/ helpers/ scripts/ Bootstrap.php news/ Bootstrap.php docs/ library/ MyApp/ Controller/ Plugin/ ModuleConfigurator.php public/ tests/Similar from [2], I registered a plugin at Bootstrap.php:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initControllerPlugins() { // Register module configurator so that it will run first and initialize the modules $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new MyApp_Controller_Plugin_ModuleConfigurator(),1); } }The Module Configurator does the following:
class MyApp_Controller_Plugin_ModuleConfigurator extends Zend_Controller_Plugin_Abstract { protected $_view; protected function moduleInit($_bootstrap, $_config) { // Run resource configurators $resources = array_keys($_config->resources->toArray()); foreach ($resources as $resourceName) { $options = $_config->resources->$resourceName; $configuratorClass = $this->_view->originalModule . '_Library_Configurator_' . ucfirst($resourceName); $configurator = new $configuratorClass($options); $configurator->setBootstrap($_bootstrap); $configurator->init(); } // Attach plugins $plugins = $_config->plugins->toArray(); foreach ($plugins as $pluginName) { $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new $pluginName()); } } public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) { // Get view $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->init(); $view = $viewRenderer->view; $this->_view = $view; // set up common variables for the view $view->originalModule = $request->getModuleName(); $view->originalController = $request->getControllerName(); $view->originalAction = $request->getActionName(); $front = Zend_Controller_Front::getInstance(); $bootstrap = $front->getParam('bootstrap'); $moduleName = $request->getModuleName(); $moduleDirectory = Zend_Controller_Front::getInstance()->getModuleDirectory($moduleName); $configPath = $moduleDirectory . DIRECTORY_SEPARATOR . 'configs' . DIRECTORY_SEPARATOR . 'module.ini'; if (file_exists($configPath)) { if (!is_readable($configPath)) { throw new Exception('modules.ini is not readable for module "' . $moduleName . '"'); } $config = new Zend_Config_Ini($configPath, $bootstrap->getEnvironment()); $this->moduleInit($bootstrap, $config); } } }So basically, what it does is that it reads the module.ini of the module, then init() every resource. Also, attach plugins if given in the module.ini. So a resource initiliazor is just a realization of a Zend_Application_Resource_ResourceAbstract, like below:
class News_Library_Configurator_Layout extends Zend_Application_Resource_ResourceAbstract { public function init() { $layout = $this->getBootstrap()->getResource('layout'); $layout->setOptions($this->getOptions()); } }Here is an example of a module.ini:
[production] resources.layout.layout = "layout" resources.layout.layoutPath = APPLICATION_PATH "/modules/Core/layouts/scripts" plugins[] = "MyApp_Controller_Plugin_ViewSetup"Each module has a specific library by autoloading it from a module bootstrap, like below:
class News_Bootstrap extends Zend_Application_Module_Bootstrap { protected function _initLibraryAutoloader() { return $this->getResourceLoader()->addResourceType('library','library','Library'); } }If all of these seems advanced to you, check out the references below, these guys explained these stuffs in great detail and I don't want to steal their spotlight (actually I'm just too lazy!)
If I miss something, just tell me! :)
References:
[1] http://www.weierophinney.net/matthew/archives/234-Module-Bootstraps-in-Zend-Framework-Dos-and-Donts.html
[2] http://blog.astrumfutura.com/2009/09/self-contained-reusable-zend-framework-modules-with-standardised-configurators/
[3] http://framework.zend.com/wiki/pages/viewpage.action?pageId=16023853
[4] http://blog.vandenbos.org/2009/07/07/zend-framework-module-config/
[5] http://binarykitten.me.uk/dev/zend-framework/177-active-module-based-config-with-zend-framework.html