[ZF-8969] Manual:
[zend.git] / documentation / manual / en / module_specs / Zend_Controller-FrontController.xml
blob8027d33ed7ac662bcba542520dafd37966e8a874
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.controller.front">
4     <title>The Front Controller</title>
6     <sect2 id="zend.controller.front.overview">
7         <title>Overview</title>
9         <para>
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.
18         </para>
20         <para>
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.
26         </para>
28         <para>
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.
35         </para>
37         <para>
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.
43         </para>
45         <note>
46             <title>Default Behaviour</title>
47             <para>
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.
54             </para>
56             <para>
57                 To disable the <emphasis>ErrorHandler</emphasis>, perform the following
58                 at any point prior to calling <methodname>dispatch()</methodname>:
59             </para>
61             <programlisting language="php"><![CDATA[
62 // Disable the ErrorHandler plugin:
63 $front->setParam('noErrorHandler', true);
64 ]]></programlisting>
66             <para>
67                 To disable the <emphasis>ViewRenderer</emphasis>, do the following prior
68                 to calling <methodname>dispatch()</methodname>:
69             </para>
71             <programlisting language="php"><![CDATA[
72 // Disable the ViewRenderer helper:
73 $front->setParam('noViewRenderer', true);
74 ]]></programlisting>
75         </note>
76     </sect2>
78     <sect2 id="zend.controller.front.methods.primary">
79         <title>Primary Methods</title>
81         <para>
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:
85         </para>
87         <sect3 id="zend.controller.front.methods.primary.getinstance">
88             <title>getInstance()</title>
90             <para>
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.
95             </para>
97             <programlisting language="php"><![CDATA[
98 $front = Zend_Controller_Front::getInstance();
99 ]]></programlisting>
100         </sect3>
102         <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
103             <title>setControllerDirectory() and addControllerDirectory</title>
105             <para>
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.
112             </para>
114             <para>
115                 As some examples:
116             </para>
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');
131 ]]></programlisting>
133             <note>
134                 <para>
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
138                     exists.
139                 </para>
140             </note>
142             <para>
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.
146             </para>
147         </sect3>
149         <sect3 id="zend.controller.front.methods.primary.addmoduledirectory">
150             <title>addModuleDirectory() and getModuleDirectory()</title>
152             <para>
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
156                 called "modules".
157             </para>
159             <para>
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.
164             </para>
166             <para>
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
170                 controller.
171             </para>
173             <para>
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.
178             </para>
179         </sect3>
181         <sect3 id="zend.controller.front.methods.primary.dispatch">
182             <title>dispatch()</title>
184             <para>
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.
192             </para>
194             <para>
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
199                 default).
200             </para>
202             <para>
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
207                 found.
208             </para>
210             <para>
211                 The dispatch process has three distinct events:
212             </para>
214             <itemizedlist>
215                 <listitem><para>Routing</para></listitem>
216                 <listitem><para>Dispatching</para></listitem>
217                 <listitem><para>Response</para></listitem>
218             </itemizedlist>
220             <para>
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
227                 response.
228             </para>
229         </sect3>
231         <sect3 id="zend.controller.front.methods.primary.run">
232             <title>run()</title>
234             <para>
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
238                 <link
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>,
242                 and finally <link
243                     linkend="zend.controller.front.methods.primary.dispatch">dispatches</link>.
244             </para>
246             <para>
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.
250             </para>
252             <programlisting language="php"><![CDATA[
253 // Instantiate front controller, set controller directory, and dispatch in one
254 // easy step:
255 Zend_Controller_Front::run('../application/controllers');
256 ]]></programlisting>
257         </sect3>
258     </sect2>
260     <sect2 id="zend.controller.front.methods.environment">
261         <title>Environmental Accessor Methods</title>
263         <para>
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.
268         </para>
270         <itemizedlist>
271             <listitem>
272                 <para>
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.
277                 </para>
278             </listitem>
280             <listitem>
281                 <para>
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>.
287                 </para>
288             </listitem>
290             <listitem>
291                 <para>
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>.
297                 </para>
298             </listitem>
300             <listitem>
301                 <para>
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.
309                 </para>
310             </listitem>
312             <listitem>
313                 <para>
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.
321                 </para>
323                 <para>
324                     When retrieving the router object, it first checks to see if
325                     one is present, and if not, instantiates the default router
326                     (rewrite router).
327                 </para>
328             </listitem>
330             <listitem>
331                 <para>
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.
338                 </para>
339             </listitem>
341             <listitem>
342                 <para>
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.
351                 </para>
353                 <para>
354                     When retrieving the dispatcher object, it first checks to see if
355                     one is present, and if not, instantiates the default
356                     dispatcher.
357                 </para>
358             </listitem>
360             <listitem>
361                 <para>
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.
369                 </para>
370             </listitem>
372             <listitem>
373                 <para>
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.
379                 </para>
380             </listitem>
382             <listitem>
383                 <para>
384                     <methodname>unregisterPlugin($plugin)</methodname> let you
385                     unregister <link
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.
389                 </para>
390             </listitem>
392             <listitem>
393                 <para>
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.
400                 </para>
402                 <para>
403                     For more information, read <link linkend="zend.controller.exceptions">MVC
404                         Exceptions</link>.
405                 </para>
406             </listitem>
408             <listitem>
409                 <para>
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
418                     behaviour.
419                 </para>
421                 <para>
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.
425                 </para>
426             </listitem>
427         </itemizedlist>
428     </sect2>
430     <sect2 id="zend.controller.front.methods.params">
431         <title>Front Controller Parameters</title>
433         <para>
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:
441         </para>
443         <itemizedlist>
444             <listitem>
445                 <para>
446                     <methodname>setParam($name, $value)</methodname> allows you to set a
447                     single parameter of <varname>$name</varname> with value
448                     <varname>$value</varname>.
449                 </para>
450             </listitem>
452             <listitem>
453                 <para>
454                     <methodname>setParams(array $params)</methodname> allows you to set
455                     multiple parameters at once using an associative array.
456                 </para>
457             </listitem>
459             <listitem>
460                 <para>
461                     <methodname>getParam($name)</methodname> allows you to retrieve a single
462                     parameter at a time, using <varname>$name</varname> as the
463                     identifier.
464                 </para>
465             </listitem>
467             <listitem>
468                 <para>
469                     <methodname>getParams()</methodname> allows you to retrieve the entire
470                     list of parameters at once.
471                 </para>
472             </listitem>
474             <listitem>
475                 <para>
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).
480                 </para>
481             </listitem>
482         </itemizedlist>
484         <para>
485             There are several pre-defined parameters that may be set that have
486             specific uses in the dispatch chain:
487         </para>
489         <itemizedlist>
490             <listitem>
491                 <para>
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.
498                 </para>
500                 <para>
501                     See <link linkend="zend.controller.exceptions.internal">MVC Exceptions
502                         You May Encounter</link>
503                     for more detailed information on using this setting.
504                 </para>
505             </listitem>
507             <listitem>
508                 <para>
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.
515                 </para>
516             </listitem>
518             <listitem>
519                 <para>
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.
523                 </para>
524             </listitem>
526             <listitem>
527                 <para>
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
531                     disable it.
532                 </para>
533             </listitem>
534         </itemizedlist>
535     </sect2>
537     <sect2 id="zend.controller.front.subclassing">
538         <title>Extending the Front Controller</title>
540         <para>
541             To extend the Front Controller, at the very minimum you will need
542             to override the <methodname>getInstance()</methodname> method:
543         </para>
545         <programlisting language="php"><![CDATA[
546 class My_Controller_Front extends Zend_Controller_Front
548     public static function getInstance()
549     {
550         if (null === self::$_instance) {
551             self::$_instance = new self();
552         }
554         return self::$_instance;
555     }
557 ]]></programlisting>
559         <para>
560             Overriding the <methodname>getInstance()</methodname> method ensures that
561             subsequent calls to
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.
566         </para>
568         <para>
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
574             dispatcher are used.
575         </para>
576     </sect2>
577 </sect1>
578 <!--
579 vim:se ts=4 sw=4 et: