Zend_Controller system was built with extensibility in mind, either
by subclassing the existing classes or writing new classes that implement
Possible reasons for implementing a new router or dispatcher might be:
The existing URI routing system is not suitable in some way, such as integrating into an existing website that uses its own conventions for routing that do not mesh with the routing mechanism provided with the Zend Framework.
You need to implement routing for something completely different. The
class only deals with URIs. It's possible and likely that you might want to use the MVC
pattern for developing another type of program, such as a console application. In the case of
a console application, a custom router could process command line arguments to determine
The mechanism provided by
Zend_Controller_Dispatcher is not suitable. The default configuration
assumes a convention that controllers are classes and actions are methods of those classes.
However, there are many other strategies for doing this. One example would be where controllers
are directories and actions are files within those directories.
You wish to provide additional capabilities that will be inherited by all of your controllers.
Zend_Controller_Action does not integrate with
Zend_View by default.
However, you could extend your own controller to do this, and using it would not require modifying the
Please be careful when overriding significant parts of the system, particularly the dispatcher. One of
the advantages of
Zend_Controller is that it establishes common conventions for building applications. If
too much of this default behavior is changed, some of these advantages are lost. However, there are many
different needs and one solution can't fit them all, so the freedom is provided if needed.
When subclassing any of the Zend_Controller classes, you are strongly encouraged to follow these conventions for naming or storing files. Doing so will ensure that another programmer who is familiar with the Zend Framework will be able to understand your project easily.
Classes included with the Zend Framework follow a convention where every class is prefixed by "Zend_". This is the prefix. We recommend that you name all of your classes in the same way, e.g. if your company name is Widget, Inc., the prefix might be "Widget_".
Zend_Controller classes are stored in the library directory as follows:
/library /Zend /Controller Action.php Dispatcher.php Router.php
Zend_Controller classes, it is recommended that the new classes
be stored in an identical structure under your prefix. This will make them easy to find for
someone during that learning process of reviewing the code for your project.
For example, a project from Widget, Inc. which implements only a custom router might look like this:
/library /Zend /Widget /Controller Router.php README.txt
Notice in this example that the
Widget/Controller/ directory mirrors the
directory wherever possible. In this case, it provides the class
which would be either a subclass or replacement for
Also, notice in the example above that a
README.txt file has been placed in
Zend strongly encourages you to document your projects through supplying separate tests and
documentation for customers. However, we encourage you to also place a simple
right in the directory to briefly explain your changes and how they work.
Zend_Controller_Router_Interface provides a definition for only one method:
<?php /** * @param Zend_Controller_Dispatcher_Interface * @throws Zend_Controller_Router_Exception * @return Zend_Controller_Dispatcher_Token|boolean */ public function route(Zend_Controller_Dispatcher_Interface $dispatcher); ?>
Routing only occurs once: when the request is first received into the system. The purpose of the
router is to generate a
Zend_Controller_Dispatch_Token that specifies a controller and action of
that controller. This is then passed to the dispatcher. If it is not possible to map a route to
a dispatch token (nonsenical route) then a boolean,
FALSE, should be returned.
Some routers may process dynamic elements and need a way to determine if the dispatch token generated
is actually dispatchable before returning it. For this reason, the router receives the object handle
of the dispatcher as the sole argument to its
route() method. The dispatcher provides a method,
isDispatchable(), for this testing.
Zend_Controller_Front will first call the router to receive the first dispatch token, which it will
pass to the dispatcher. The dispatcher will dispatch the action (instantiate the controller, call
its action) and then return with either a boolean, FALSE, or another dispatch token.
Zend_Controller_Front repeatedly calls the dispatcher until a dispatch token is not returned from
it. This is known as the dispatch loop. It allows for actions to be processed sequentially
until all work has been done.
Zend_Controller_Dispatcher_Interface provides definitions for two methods:
<?php /** * @param Zend_Controller_Dispatcher_Token $route * @return boolean */ public function isDispatchable(Zend_Controller_Dispatcher_Token $route); ?>
isDispatchable() checks if a dispatch token is dispatchable. If it is, it returns
Otherwise, it returns
FALSE. The definition of what is dispatchable is left to the class
implementing the interface. In the case of the default implementation,
Zend_Controller_Dispatcher, it means
that the controller file exists, the class exists within the file, and the action method exists within the class.
<?php /** * @param Zend_Controller_Dispatcher_Token $route * @return Zend_Controller_Dispatcher_Token|boolean */ public function dispatch(Zend_Controller_Dispatcher_Token $route); ?>
dispatch() is where the work gets done. This method must execute the action of the controller.
It must return either a dispatch token or a boolean, FALSE, to indicate that there is no more work to do.