The Conventional Modular directory structure allows you to separate different MVC applications into self-contained units, and re-use them with different front controllers. To illustrate such a directory structure:
docroot/ index.php application/ controllers/ IndexController.php FooController.php blog/ controllers/ IndexController.php models/ views/ news/ controllers/ IndexController.php ListController.php models/ views/
In this paradigm, the module name serves as a prefix to the controllers it contains. The above example contains three module controllers, 'Blog_IndexController', 'News_IndexController', and 'News_ListController'. Two global controllers, 'IndexController' and 'FooController' are also defined; neither of these will be namespaced. This directory structure will be used for examples in this chapter.
So, how do you implement such a directory layout using the Zend Framework MVC components?
The first step to making use of modules is to modify how you specify the controller directory list in the front controller. In the basic MVC series, you pass either an array or a string to setControllerDirectory(), or a path to addControllerDirectory(). When using modules, you need to alter your calls to these methods slightly.
With setControllerDirectory(), you will need to pass an associative array and specify key/value pairs of module name/directory paths. The special key 'default' will be used for global controllers (those not needing a module namespace), and can contain an array of paths. All others need a string key pointing to a single path. As an example:
$front->setControllerDirectory(array( 'default' => array('/path/to/application/controllers'), 'blog' => '/path/to/application/blog/controllers' ));
addControllerDirectory() will take an optional second argument. When using modules, pass the module name as the second argument; if not specified, the path will be added to the default namespace. As an example:
$front->addControllerDirectory('/path/to/application/news/controllers', 'news');
In addition to changing how you specify the controller directories, you will also need to use a module-aware router and dispatcher. You can choose either Zend_Controller_ModuleRouter or Zend_Controller_ModuleRewriteRouter for the router, and Zend_Controller_ModuleDispatcher for the dispatcher. To do so, modify your front controller bootstrap slightly:
require_once 'Zend/Controller/ModuleRouter.php'; require_once 'Zend/Controller/ModuleDispatcher.php'; $front->setRouter(new Zend_Controller_ModuleRouter()) ->setDispatcher(new Zend_Controller_ModuleDispatcher())
From this point forward, dispatch the front controller as normal:
$front->dispatch();
Zend_Controller_ModuleRouter will only match a module if a matching key exists in the controller directory array; otherwise, it falls back on the default behaviour of matching /controller/action.
In the default router, if a controller was not specified in the URL, a default controller is used (IndexController, unless otherwise requested). With modular controllers, if a module has been specified but no controller, the dispatcher first looks for this default controller in the module path, and then falls back on the default controller found in the 'default', global, namespace.
If you wish to always default to the global namespace, set the 'useGlobalDefault' parameter in the front controller:
$front->setParam('useGlobalDefault', true);