Nick Lo wrote:
One of the directory layouts, "Conventional Modular", was particularly
interesting and seems to be a fairly logical way to organise modular
ZF applications...
/application
/config (optional)
/(module1)
/config (optional as needed)
/controllers
/models
/views
/(module2)
/controllers
/models
/views
/(modulen)
/controllers
/models
/views
For what it's worth, I've been using some preDispatch code to allow a
similar structure (or similar to this - it wasn't preDispatch at the
beginning) ever since I started using ZF (which will probably be
superceded sometime soon I know - but it's here in case it helps anyone):
/application
/config
/controllers
/ModulesController.php // See example below
/models
/modules
/module1
/controllers
/models
/views
/modulen
/controllers
/models
/views
/whois
/controllers
/WhoisController.php // See example route below
/views
/views
ModulesController.php - uses a define (MODULES_PATH) for the path to the
modules folder:
class ModulesController extends Zend_Controller_Action {
public function init() {
parent::init();
}
public function preDispatch () {
// Get the Front controller from the registry
$ctrl = Zend::registry('ctrl_front');
$module = $this->_getParam('module', 'default');
$controller = $this->_getParam('module_controller', 'index');
$action = $this->_getParam('module_action', 'index');
$path = MODULES_PATH . DIRECTORY_SEPARATOR . $module .
DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR;
$file = ucfirst($controller) . 'Controller.php';
// Check if the module and controller file exist
if (file_exists($path . $file) && is_readable($path . $file)) {
// Set the Modules controller path
$dispatcher = $ctrl->getDispatcher();
$dispatcher->setControllerDirectory($path);
// Add the module path to the include path for any local module files
if (!strstr(get_include_path(), $path)) {
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
}
// Forward to the appropriate module
$this->_forward($controller, $action, $this->_getAllParams());
} else {
$this->noRouteAction();
}
}
public function indexAction () {
}
}
The other piece that makes this work is the routing (from index.php):
$router = new Zend_Controller_RewriteRouter();
$default = new Zend_Controller_Router_Route('', array('module' =>
'default', 'module_controller' => 'index', 'module_action' => 'index',
'controller' => 'modules', 'action' => 'index'));
//And an example for a whois module:
$route_whois = new Zend_Controller_Router_Route('whois/:domain/*',
array('module' => 'whois', 'module_controller' => 'whois',
'module_action' => 'index', 'controller' => 'modules', 'action' =>
'index'));
// or for more general /modules/modulename behaviour:
$route_modules3 = new
Zend_Controller_Router_Route('modules/:module/:module_controller/:module_action/*',
array('module' => 'default', 'module_controller' => 'index',
'module_action' => 'index', 'controller' => 'modules', 'action' =>
'index'), array('module' =>
'(list|of|acceptable|modules|to|choose|from)+', 'module_controller' =>
'(list|of|acceptable|controllers)+', 'module_action' =>
'(list|of|acceptable|actions)+'));
$route_modules2 = new
Zend_Controller_Router_Route('modules/:module/:module_controller/*',
array('module' => 'default', 'module_controller' => 'index',
'module_action' => 'index', 'controller' => 'modules', 'action' =>
'index'), array('module' =>
'(list|of|acceptable|modules|to|choose|from)+', 'module_controller' =>
'(list|of|acceptable|controllers)+'));
$route_modules1 = new Zend_Controller_Router_Route('modules/:module/*',
array('module' => 'default', 'module_controller' => 'index',
'module_action' => 'index', 'controller' => 'modules', 'action' =>
'index'));
/**
* Routes are matched in reverse order so make sure your most generic
routes are defined first.
*/
$routes = array();
$routes['default'] = $route_default;
$routes['modules1'] = $route_modules1;
$routes['modules2'] = $route_modules2;
$routes['modules3'] = $route_modules3;
$routes['whois'] = $route_whois;
$router->addRoutes($routes);
$request = new Zend_Controller_Request_Http();
$ctrl = Zend_Controller_Front::getInstance();
Zend::register('ctrl_front', $ctrl);
$ctrl->setControllerDirectory(CONTROLLERS_PATH); // Defined before
$ctrl->setRequest($request);
$ctrl->setRouter($router);
$response = $ctrl->dispatch();
Hope that helps someone - it works nicely for me.
Jeremy