Programmer's Reference Guide
| Plugins |
Using a Conventional Modular Directory Structure
Introduction
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/
- default/
- controllers/
- IndexController.php
- FooController.php
- models/
- views/
- scripts/
- index/
- foo/
- helpers/
- filters/
- blog/
- controllers/
- IndexController.php
- models/
- views/
- scripts/
- index/
- helpers/
- filters/
- news/
- controllers/
- IndexController.php
- ListController.php
- models/
- views/
- scripts/
- index/
- list/
- helpers/
- filters/
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.
Note: No Namespacing in the Default Module
Note that in the default module, controllers do not need a namespace prefix. Thus, in the example above, the controllers in the default module do not need a prefix of 'Default_' -- they are simply dispatched according to their base controller name: 'IndexController' and 'FooController'. A namespace prefix is used in all other modules, however.
So, how do you implement such a directory layout using the Zend Framework MVC components?
Specifying Module Controller Directories
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 and value pairs of module name and directory paths. The special key default will be used for global controllers (those not needing a module namespace). All entries should contain a string key pointing to a single path, and the default key must be present. As an example:
- 'default' => '/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');
Saving the best for last, the easiest way to specify module directories is to do so en masse, with all modules under a common directory and sharing the same structure. This can be done with addModuleDirectory():
- /**
- * Assuming the following directory structure:
- * application/
- * modules/
- * default/
- * controllers/
- * foo/
- * controllers/
- * bar/
- * controllers/
- */
- $front->addModuleDirectory('/path/to/application/modules');
The above example will define the default, foo, and bar modules, each pointing to the controllers/ subdirectory of their respective module.
You may customize the controller subdirectory to use within your modules by using setModuleControllerDirectoryName():
- /**
- * Change the controllers subdirectory to be 'con'
- * application/
- * modules/
- * default/
- * con/
- * foo/
- * con/
- * bar/
- * con/
- */
- $front->setModuleControllerDirectoryName('con');
- $front->addModuleDirectory('/path/to/application/modules');
Note: You can indicate that no controller subdirectory be used for your modules by passing an empty value to setModuleControllerDirectoryName().
Routing to Modules
The default route in Zend_Controller_Router_Rewrite is an object of type Zend_Controller_Router_Route_Module. This route expects one of the following routing schemas:
:module/:controller/:action/*
:controller/:action/*
In other words, it will match a controller and action by themselves or with a preceding module. The rules for matching specify that a module will only be matched if a key of the same name exists in the controller directory array passed to the front controller and dispatcher.
Module or Global Default Controller
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 $useDefaultControllerAlways parameter in the front controller:
- $front->setParam('useDefaultControllerAlways', true);
| Plugins |
Add A Comment
Please do not report issues via comments; use the ZF Issue Tracker.
If you have a JIRA/Crowd account, we suggest you login first before commenting.
Select a Version
Languages Available
Components
Search the Manual
Navigation
- Programmer's Reference Guide
- Programmer's Reference Guide
- Zend Framework Reference
- Zend_Controller
- Zend_Controller Quick Start
- Zend_Controller Basics
- The Front Controller
- The Request Object
- The Standard Router
- The Dispatcher
- Action Controllers
- Action Helpers
- The Response Object
- Plugins
- Using a Conventional Modular Directory Structure
- MVC Exceptions

Comments
where the default module is a level higher than the modules directory.
yes
This is the same problem throughout the ZF documentation! Stop crapping on about how awesome the framework is and put the examples in CONTEXT!
The layout shipped with ZF is implemented as a front controller plugin.
You can easily extend that one and work some magic to switch the layout according to the requested module. And configure the layout resource to use your own class.
My take (on pastebin) :
http://pastebin.org/358208
And in application.ini :
resources.layout.layout = layout
resources.layout.layoutPath = APPLICATION_PATH "/views/layouts"
resources.layout.pluginClass = "My_Controller_Plugin_ModuleLayout"
See: http://www.theinquirer.net/inquirer/news/1023739/windows
I've tried to configure in my bootstrap,
public function run()
{
parent::run();
$front = $this->getResource('FrontController');
$front->addModuleDirectory('application/modules');
}
and this appears to work (no exceptions thrown) but to no avail, I still need to include or require.
In which file?
The following should be added to your Bootstrap.php file.
protected function _initFrontModules() {
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$front->addModuleDirectory(APPLICATION_PATH . '/modules');
}
The following should be added to your Bootstrap.php file.
protected function _initFrontModules() {
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$front->addModuleDirectory(APPLICATION_PATH . '/modules');
}
Why not explore some example rather than commend.
Example gere : http://updel.com/zend-framework-modular-application/
I was starting to again feel like, if I don't just know, then why am at Zend.com trying to find the answer. I mean, c'mon, with the above being so clear now. pff
application
default
controllers
models
views
admin
controllers
models
views
and i want to keep all my models in default/models and all modules can use. How can i do this???
When i made the class 'Apllication_Model_Test' the class was not found. What and WHERE i have to set up for i use my models on all modules?
Thanks for any help!!!
Renan30
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules=true
and removing the line
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
I used zend tool:
zf create module default
Which adds a directories into : APPLICATION_PATH /modules/default
and appends to the application.ini config file:
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.params.prefixDefaultModule = "1"
I then moved my IndexController, ErrorController and view scripts into the default module's appropriate directories but got this error:
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller class ("Default_ErrorController")'Removing this line from application.ini solves this problem:
resources.frontController.params.prefixDefaultModule = "1"resources.frontController.params.prefixDefaultModule = ""
$ front-> setControllerDirectory (array (
'default' => '/ path / to / application / controllers',
'blog' => '/ path / to / application / blog / controllers'
));
All examples, tutorials or the vast majority do not understand what part they copied the codes mentioned, that I tell people that just start with zend.
I solved the problem by using this:
resources.frontController.prefixDefaultModule = "Default"
Don't remove "Default" from ErrorController because it seems not to be natural. What if you don't want the default module named "default"? :)
And how can i load a model class which is located in "modules/news/models/news.php"?
It depends exactly on how you have named things. Here is how I solved the same problem.
My file structure is:
application > modules > module which contains a folder for controllers, models, views and a Bootstrap.php file.
My module Bootstrap.php file is:
class modulename_Bootstrap extends Zend_Application_Module_Bootstrap
{
}
I created a basic model which looks something like this:
class Module_Model_Bio
{
public function fetchAll()
{
// fetch all records from the table
$rowset = $this->_dbTable->fetchAll();
return $rowset->toArray();
} //end fetchAll
}
Then in my controller, I can instantiate this model with the following (note the lowercase module after the keyword new):
class Module_BioController extends Zend_Controller_Action
{
public function indexAction()
{
[b]$bio = new module_Model_Bio();[/b]
$this->view->entries = $bio->fetchAll();
}
}
I could be wrong, but I believe it is lowercase because that is how my module was named and how it is written in my module's Bootstrap.php file. If I instantiate it in a different case (camel case) it will not be found.
Please note the rule following line:
[b]$bio = new module_Model_Bio();[/b]
should just be:
$bio = new module_Model_Bio();
http://www.ranweb.net/wpEn/?p=406
Maybe it will help somebody...