Modules

One of the new features to hit the Zend Framework since 0.7 is Zend_Controller_ModuleRouter and its sibling Zend_Controller_ModuleRewriteRouter. This allows for separating out sets of controlers, models and views into their own modules. The directory structure then looks like:

application/
    controllers/
        IndexController.php
        ArticleController.php
    blog/
        controllers/
            IndexController.php
        models/
        views/
    news/
        controllers/
            IndexController.php
            ListController.php
        models/
        views/
    models/
    views/
lib/
    Zend/
webroot/
	css/
	img/
	js/
	index.php

To set this up, you use this code in index.php:


$frontController->setControllerDirectory(array( 
      'default' => array('../application/controllers'), 
      'blog'    => '../application/blog/controllers', 
      'news'    => '../application/news/controllers' 
)); 
$frontController->setRouter(new Zend_Controller_ModuleRouter()) 
      ->setDispatcher(new Zend_Controller_ModuleDispatcher()) 

The module router then maps the first parameter of the URL to the module and so then looks for a controller within that module's controllers directory. Hence http://www.example.com/news/list/recent will map to the News_ListController::recentAction() in the ../application/news/controllers directory. If the first parameter is not a named module, then the default module is used and the first parameter is considered to be the controller instead. In this case http://www.example.com/article/list will map to ArticleController::listAction() in the ../application/controllers directory.

It's all very clever.

One issue with the directory layout above is that the controllers within the default route will need models and views too. These are within the application directory itself an so interspersed with the module directories; feels a bit untidy to me. It makes more sense to me to create a directory called default to hold the three directories:

application/
    blog/
        controllers/
            IndexController.php
        models/
        views/
    default/
        controllers/
            IndexController.php
            ArticleController.php
        models/
        views/
    news/
        controllers/
            IndexController.php
            ListController.php
        models/
        views/
lib/
    Zend/
webroot/
	css/
	img/
	js/
	index.php

with the set up code in index.php becoming:
To set this up, you use this code in index.php:


$frontController->setControllerDirectory(array( 
      'default' => array('../application/default/controllers'), 
      'blog'    => '../application/blog/controllers', 
      'news'    => '../application/news/controllers' 
)); 
$frontController->setRouter(new Zend_Controller_ModuleRouter()) 
      ->setDispatcher(new Zend_Controller_ModuleDispatcher()) 

This now nicely keeps the MVC componts together and seems to work quite well. What I'm not sure of is how to handle an admin site. I suspect that the rewrite module router is the way to do this. I'm now into guesswork though, so will have to actually write some code in my IDE and see what happens.
I'm not sure what directory structure I want yet either.
If we take the news module:

    news/
        controllers/
            IndexController.php
            ListController.php
        models/
        views/

Do I want to put admin with it?

    news/
        controllers/
            admin/
                IndexController.php
            IndexController.php
            ListController.php
        models/
        views/
            admin/

Or do I want a separate adminNews module? It's likely that the models used by news and adminNews will be the same (or adminNews will use a super-set of the news model), so I can see the logic of putting the admin code within the same set of directories.

Maybe I think too much about these sort of issues!

If you would like to comment on this article, please ping me on twitter.
If your response won't fit into 140 characters, write a blog post and then ping me!