1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.controller.front">
4 <title>The Front Controller</title>
6 <sect2 id="zend.controller.front.overview">
7 <title>Overview</title>
10 <classname>Zend_Controller_Front</classname> implements a <ulink
11 url="http://www.martinfowler.com/eaaCatalog/frontController.html">Front
12 Controller pattern</ulink> used in <ulink
13 url="http://en.wikipedia.org/wiki/Model-view-controller">Model-View-Controller
14 (MVC)</ulink> applications. Its purpose is to initialize the
15 request environment, route the incoming request, and then dispatch
16 any discovered actions; it aggregates any responses and returns them
17 when the process is complete.
21 <classname>Zend_Controller_Front</classname> also implements the <ulink
22 url="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton
23 pattern</ulink>, meaning only a single instance of it may be available at
24 any given time. This allows it to also act as a registry on which
25 the other objects in the dispatch process may draw.
29 <classname>Zend_Controller_Front</classname> registers a <link
30 linkend="zend.controller.plugins">plugin broker</link> with
31 itself, allowing various events it triggers to be observed by
32 plugins. In most cases, this gives the developer the opportunity to
33 tailor the dispatch process to the site without the need to extend
34 the front controller to add functionality.
38 At a bare minimum, the front controller needs one or more paths to
39 directories containing <link linkend="zend.controller.action">action
40 controllers</link> in order to do its work. A variety of methods
41 may also be invoked to further tailor the front controller
42 environment and that of its helper classes.
46 <title>Default Behaviour</title>
48 By default, the front controller loads the <link
49 linkend="zend.controller.plugins.standard.errorhandler">ErrorHandler</link>
50 plugin, as well as the <link
51 linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>
52 action helper plugin. These are to simplify error handling and
53 view renderering in your controllers, respectively.
57 To disable the <emphasis>ErrorHandler</emphasis>, perform the following
58 at any point prior to calling <methodname>dispatch()</methodname>:
61 <programlisting language="php"><![CDATA[
62 // Disable the ErrorHandler plugin:
63 $front->setParam('noErrorHandler', true);
67 To disable the <emphasis>ViewRenderer</emphasis>, do the following prior
68 to calling <methodname>dispatch()</methodname>:
71 <programlisting language="php"><![CDATA[
72 // Disable the ViewRenderer helper:
73 $front->setParam('noViewRenderer', true);
78 <sect2 id="zend.controller.front.methods.primary">
79 <title>Primary Methods</title>
82 The front controller has several accessors for setting up its
83 environment. However, there are three primary methods key to the
84 front controller's functionality:
87 <sect3 id="zend.controller.front.methods.primary.getinstance">
88 <title>getInstance()</title>
91 <methodname>getInstance()</methodname> is used to retrieve a front
92 controller instance. As the front controller implements a
93 Singleton pattern, this is also the only means possible for
94 instantiating a front controller object.
97 <programlisting language="php"><![CDATA[
98 $front = Zend_Controller_Front::getInstance();
102 <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
103 <title>setControllerDirectory() and addControllerDirectory</title>
106 <methodname>setControllerDirectory()</methodname> is used to tell <link
107 linkend="zend.controller.dispatcher">the dispatcher</link>
108 where to look for <link
109 linkend="zend.controller.action">action controller</link>
110 class files. It accepts either a single path or an associative
111 array of module and path pairs.
118 <programlisting language="php"><![CDATA[
119 // Set the default controller directory:
120 $front->setControllerDirectory('../application/controllers');
122 // Set several module directories at once:
123 $front->setControllerDirectory(array(
124 'default' => '../application/controllers',
125 'blog' => '../modules/blog/controllers',
126 'news' => '../modules/news/controllers',
129 // Add a 'foo' module directory:
130 $front->addControllerDirectory('../modules/foo/controllers', 'foo');
135 If you use <methodname>addControllerDirectory()</methodname> without a
136 module name, it will set the directory for the
137 <emphasis>default</emphasis> module -- overwriting it if it already
143 You can get the current settings for the controller directory
144 using <methodname>getControllerDirectory()</methodname>; this will return an
145 array of module and directory pairs.
149 <sect3 id="zend.controller.front.methods.primary.addmoduledirectory">
150 <title>addModuleDirectory() and getModuleDirectory()</title>
153 One aspect of the front controller is that you may <link
154 linkend="zend.controller.modular">define a modular directory
155 structure</link> for creating standalone components; these are
160 Each module should be in its own directory and mirror the
161 directory structure of the default module -- i.e., it should
162 have a <filename>/controllers/</filename> subdirectory at the minimum, and typically
163 a <filename>/views/</filename> subdirectory and other application subdirectories.
167 <methodname>addModuleDirectory()</methodname> allows you to pass the name of
168 a directory containing one or more module directories. It then
169 scans it and adds them as controller directories to the front
174 Later, if you want to determine the path to a particular module
175 or the current module, you can call
176 <methodname>getModuleDirectory()</methodname>, optionally passing a module
177 name to get that specific module directory.
181 <sect3 id="zend.controller.front.methods.primary.dispatch">
182 <title>dispatch()</title>
185 <methodname>dispatch(Zend_Controller_Request_Abstract $request = null,
186 Zend_Controller_Response_Abstract $response = null)</methodname>
187 does the heavy work of the front controller. It may optionally
188 take a <link linkend="zend.controller.request">request
189 object</link> and/or a <link
190 linkend="zend.controller.response">response object</link>,
191 allowing the developer to pass in custom objects for each.
195 If no request or response object are passed in,
196 <methodname>dispatch()</methodname> will check for previously registered
197 objects and use those or instantiate default versions to use in
198 its process (in both cases, the <acronym>HTTP</acronym> flavor will be used as the
203 Similarly, <methodname>dispatch()</methodname> checks for registered <link
204 linkend="zend.controller.router">router</link> and <link
205 linkend="zend.controller.dispatcher">dispatcher</link>
206 objects, instantiating the default versions of each if none is
211 The dispatch process has three distinct events:
215 <listitem><para>Routing</para></listitem>
216 <listitem><para>Dispatching</para></listitem>
217 <listitem><para>Response</para></listitem>
221 Routing takes place exactly once, using the values in the
222 request object when <methodname>dispatch()</methodname> is called.
223 Dispatching takes place in a loop; a request may either indicate
224 multiple actions to dispatch, or the controller or a plugin may
225 reset the request object to force additional actions to
226 dispatch. When all is done, the front controller returns a
231 <sect3 id="zend.controller.front.methods.primary.run">
235 <methodname>Zend_Controller_Front::run($path)</methodname> is a static
236 method taking simply a path to a directory containing
237 controllers. It fetches a front controller instance (via
239 linkend="zend.controller.front.methods.primary.getinstance">getInstance()</link>,
240 registers the path provided via <link
241 linkend="zend.controller.front.methods.primary.setcontrollerdirectory">setControllerDirectory()</link>,
243 linkend="zend.controller.front.methods.primary.dispatch">dispatches</link>.
247 Basically, <methodname>run()</methodname> is a convenience method that can
248 be used for site setups that do not require customization of the
249 front controller environment.
252 <programlisting language="php"><![CDATA[
253 // Instantiate front controller, set controller directory, and dispatch in one
255 Zend_Controller_Front::run('../application/controllers');
260 <sect2 id="zend.controller.front.methods.environment">
261 <title>Environmental Accessor Methods</title>
264 In addition to the methods listed above, there are a number of
265 accessor methods that can be used to affect the front controller
266 environment -- and thus the environment of the classes to which the
267 front controller delegates.
273 <methodname>resetInstance()</methodname> can be used to clear all
274 current settings. Its primary purpose is for testing, but it
275 can also be used for instances where you wish to chain
276 together multiple front controllers.
282 <methodname>setDefaultControllerName()</methodname> and
283 <methodname>getDefaultControllerName()</methodname> let you
284 specify a different name to use for the default controller
285 ('index' is used otherwise) and retrieve the current value.
286 They proxy to <link linkend="zend.controller.dispatcher">the dispatcher</link>.
292 <methodname>setDefaultAction()</methodname> and
293 <methodname>getDefaultAction()</methodname> let you specify a
294 different name to use for the default action ('index' is
295 used otherwise) and retrieve the current value. They proxy
296 to <link linkend="zend.controller.dispatcher">the dispatcher</link>.
302 <methodname>setRequest()</methodname> and
303 <methodname>getRequest()</methodname> let you specify <link
304 linkend="zend.controller.request">the request</link>
305 class or object to use during the dispatch process and to
306 retrieve the current object. When setting the request
307 object, you may pass in a request class name, in which case
308 the method will load the class file and instantiate it.
314 <methodname>setRouter()</methodname>
315 <methodname>getRouter()</methodname> let you specify <link
316 linkend="zend.controller.router">the router</link>
317 class or object to use during the dispatch process and to
318 retrieve the current object. When setting the router
319 object, you may pass in a router class name, in which case
320 the method will load the class file and instantiate it.
324 When retrieving the router object, it first checks to see if
325 one is present, and if not, instantiates the default router
332 <methodname>setBaseUrl()</methodname> and
333 <methodname>getBaseUrl()</methodname> let you specify <link
334 linkend="zend.controller.request.http.baseurl">the base
335 <acronym>URL</acronym></link> to strip when routing requests and to
336 retrieve the current value. The value is provided to the
337 request object just prior to routing.
343 <methodname>setDispatcher()</methodname> and
344 <methodname>getDispatcher()</methodname> let you specify <link
345 linkend="zend.controller.dispatcher">the
346 dispatcher</link> class or object to use during the
347 dispatch process and retrieve the current object. When
348 setting the dispatcher object, you may pass in a dispatcher
349 class name, in which case the method will load the class
350 file and instantiate it.
354 When retrieving the dispatcher object, it first checks to see if
355 one is present, and if not, instantiates the default
362 <methodname>setResponse()</methodname> and
363 <methodname>getResponse()</methodname> let you specify <link
364 linkend="zend.controller.response">the response</link>
365 class or object to use during the dispatch process and to
366 retrieve the current object. When setting the response
367 object, you may pass in a response class name, in which case
368 the method will load the class file and instantiate it.
374 <methodname>registerPlugin(Zend_Controller_Plugin_Abstract $plugin,
375 $stackIndex = null)</methodname> allows you to register <link
376 linkend="zend.controller.plugins">plugin objects</link>.
377 By setting the optional <varname>$stackIndex</varname>, you can
378 control the order in which plugins will execute.
384 <methodname>unregisterPlugin($plugin)</methodname> let you
386 linkend="zend.controller.plugins">plugin objects</link>.
387 <varname>$plugin</varname> may be either a plugin object or a
388 string denoting the class of plugin to unregister.
394 <methodname>throwExceptions($flag)</methodname> is used to turn on/off
395 the ability to throw exceptions during the dispatch process.
396 By default, exceptions are caught and placed in the <link
397 linkend="zend.controller.response">response
398 object</link>; turning on <methodname>throwExceptions()</methodname>
399 will override this behaviour.
403 For more information, read <link linkend="zend.controller.exceptions">MVC
410 <methodname>returnResponse($flag)</methodname> is used to tell the front
411 controller whether to return the response
412 (<constant>TRUE</constant>) from <methodname>dispatch()</methodname>, or if the
413 response should be automatically emitted
414 (<constant>FALSE</constant>). By default, the response is
415 automatically emitted (by calling
416 <methodname>Zend_Controller_Response_Abstract::sendResponse()</methodname>);
417 turning on <methodname>returnResponse()</methodname> will override this
422 Reasons to return the response include a desire to check for
423 exceptions prior to emitting the response, needing to log
424 various aspects of the response (such as headers), etc.
430 <sect2 id="zend.controller.front.methods.params">
431 <title>Front Controller Parameters</title>
434 In the introduction, we indicated that the front controller also
435 acts as a registry for the various controller components. It does so
436 through a family of "param" methods. These methods allow you to
437 register arbitrary data -- objects and variables -- with the front
438 controller to be retrieved at any time in the dispatch chain. These
439 values are passed on to the router, dispatcher, and action
440 controllers. The methods include:
446 <methodname>setParam($name, $value)</methodname> allows you to set a
447 single parameter of <varname>$name</varname> with value
448 <varname>$value</varname>.
454 <methodname>setParams(array $params)</methodname> allows you to set
455 multiple parameters at once using an associative array.
461 <methodname>getParam($name)</methodname> allows you to retrieve a single
462 parameter at a time, using <varname>$name</varname> as the
469 <methodname>getParams()</methodname> allows you to retrieve the entire
470 list of parameters at once.
476 <methodname>clearParams()</methodname> allows you to clear a single
477 parameter (by passing a string identifier), multiple named
478 parameters (by passing an array of string identifiers), or the
479 entire parameter stack (by passing nothing).
485 There are several pre-defined parameters that may be set that have
486 specific uses in the dispatch chain:
492 <emphasis>useDefaultControllerAlways</emphasis> is used to hint to
493 <link linkend="zend.controller.dispatcher">the
494 dispatcher</link> to use the default controller in the
495 default module for any request that is not dispatchable
496 (i.e., the module, controller, and/or action do not exist).
497 By default, this is off.
501 See <link linkend="zend.controller.exceptions.internal">MVC Exceptions
502 You May Encounter</link>
503 for more detailed information on using this setting.
509 <emphasis>disableOutputBuffering</emphasis> is used to hint to <link
510 linkend="zend.controller.dispatcher">the
511 dispatcher</link> that it should not use output
512 buffering to capture output generated by action controllers.
513 By default, the dispatcher captures any output and appends
514 it to the response object body content.
520 <emphasis>noViewRenderer</emphasis> is used to disable the <link
521 linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
522 Set this parameter to <constant>TRUE</constant> to disable it.
528 <emphasis>noErrorHandler</emphasis> is used to disable the <link
529 linkend="zend.controller.plugins.standard.errorhandler">Error
530 Handler plugin</link>. Set this parameter to <constant>TRUE</constant> to
537 <sect2 id="zend.controller.front.subclassing">
538 <title>Extending the Front Controller</title>
541 To extend the Front Controller, at the very minimum you will need
542 to override the <methodname>getInstance()</methodname> method:
545 <programlisting language="php"><![CDATA[
546 class My_Controller_Front extends Zend_Controller_Front
548 public static function getInstance()
550 if (null === self::$_instance) {
551 self::$_instance = new self();
554 return self::$_instance;
560 Overriding the <methodname>getInstance()</methodname> method ensures that
562 <methodname>Zend_Controller_Front::getInstance()</methodname> will return an
563 instance of your new subclass instead of a
564 <classname>Zend_Controller_Front</classname> instance -- this is particularly
565 useful for some of the alternate routers and view helpers.
569 Typically, you will not need to subclass the front controller unless
570 you need to add new functionality (for instance, a plugin
571 autoloader, or a way to specify action helper paths). Some points
572 where you may want to alter behaviour may include modifying how
573 controller directories are stored, or what default router or