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 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).
All entries should contain a string key pointing to a single path,
and the default
key must be present. As an example:
<?php $front->setControllerDirectory(array( '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:
<?php $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 masses, with all modules under a common
directory and sharing the same structure. This can be done with
addModuleDirectory()
:
<?php /** * 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()
:
<?php /** * 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
|
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.
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:
<?php $front->setParam('useGlobalDefault', true); ?>