I would like to touch this subject again. I think I have found a solution which should suit everybody as it's very easy to manage from a user standpoint and also easy to implement.

===============================================================================
Framework user standpoint

It's a concept of named modules. Let's work on a use case first - let's bootstrap our application with additional directories in the standard way:

require_once 'Zend/Controller/Front.php';
$controller = Zend_Controller_Front::getInstance();

$dirs = array(
        'default' => '/home/martel/WWW/test/controllers',
        'forum'   => '/home/martel/WWW/test/controllers/forum',
        'admin'   => '/home/martel/WWW/test/controllers/admin',
        'other'   => '/var/www/even/outside/root/dir'
);

$controller->setControllerDirectory($dirs);
echo $controller->dispatch();

As you see, it's a standard and already working way of setting controller dirs. Nothing is or needs to be changed up to this point. We can access all the dirs the standard framework way:

http://localhost/test/index.php?controller=news&action=add

But what happens when you want a NewsController in default as well as admin directories. Former is used to display news to the users and latter to administer the site.

So let's assume we have an additional parameter to use named 'module'. And if we would like to access the admin module specifically, we would use the following URIs:

With standard URL Scheme:
http://localhost/test/index.php?module=admin&controller=news&action=add

Or with RewriteRouter (route: ':module/:controller:/:action'):
http://localhost/test/admin/news/add

This way we can access any directory structure by using named modules. And what's moreover, we can have controllers named exactly the same in different directiories - something that is not possible with current codebase.

But it's a backwards compatible solution - we can still access the controllers without relying on modules. In that case dispatcher would still iterate through all the defined controller dirs like it is being done right now.

That's from the users standpoint. Now let's get to the implementation.

===============================================================================
Framework Code

It's really easy thing to do as setControllerDir is already setting directories by the key, so it's only a matter of modifying _getController() method of the dispatcher to be aware of modules (new code is marked by pluses):

protected function _getController($request, $module = null, $directories = null)
{
    ...

    $className = $this->formatControllerName($controllerName);

    /**
     * Determine if controller is dispatchable
     */
    $dispatchable = false;

+    if ($module !== null) {
+        $dispatchable = = Zend::isReadable($directory[$module]);
+    } else {
        foreach ($directories as $directory) {
            $dispatchable = Zend::isReadable($directory ...);
            if ($dispatchable) break;
        }
+    }

    return $dispatchable ? $className : false;
}

And that's pretty much it. Of course we would still have to add formatModuleName family of methods (similar to controller and action names), an optional module parameter to addControllerDir to make it store directories under specified key and finally a delegate methods in Front Controller.

public function addControllerDirectory($path, $module = null)

Finally it would probably be a good idea to move "Determine if controller is dispatchable" block out to it's own method. It will allow for easier subclassing and will meet Rob's request:

http://www.nabble.com/%24_GET%2C%24_POST-and-Zend_Controller_Request_Http-tf2710146s16154.html

===============================================================================
Backwards compatibility

This implementation is fully backwards compatible but maybe it would be better to drop backwards compatibility in order to clean the code? I mean make one default module instead of directory iteration, etc. And we're already shooting our foots with parameter ordering (parameters renamed to better show what's on my mind):

public function addControllerDirectory($dir, $name)
public function addRoute($name, $route)

--
Michael Minicki aka Martel Valgoerad | [EMAIL PROTECTED] | 
http://aie.pl/martel.asc
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
"To err is human -- and to blame it on a computer is even more so." -- Robert
Orben

Reply via email to