[MANUAL] English:
[zend.git] / documentation / manual / en / module_specs / Zend_Controller-Response.xml
bloba057ba964fe21a1485a6ed1985c357c99171743c
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.controller.response">
4     <title>The Response Object</title>
6     <sect2 id="zend.controller.response.usage">
7         <title>Usage</title>
9         <para>
10             The response object is the logical counterpart to the <link
11                 linkend="zend.controller.request">request object</link>. Its
12             purpose is to collate content and/or headers so that they may be
13             returned en masse. Additionally, the front controller will pass any
14             caught exceptions to the response object, allowing the developer to
15             gracefully handle exceptions. This functionality may be overridden
16             by setting
17             <methodname>Zend_Controller_Front::throwExceptions(true)</methodname>:
18         </para>
20         <programlisting language="php"><![CDATA[
21 $front->throwExceptions(true);
22 ]]></programlisting>
24         <para>
25             To send the response output, including headers, use
26             <methodname>sendResponse()</methodname>.
27         </para>
29         <programlisting language="php"><![CDATA[
30 $response->sendResponse();
31 ]]></programlisting>
33         <note>
34             <para>
35                 By default, the front controller calls <methodname>sendResponse()</methodname>
36                 when it has finished dispatching the request; typically you will
37                 never need to call it. However, if you wish to manipulate the
38                 response or use it in testing, you can override this
39                 behaviour by setting the <property>returnResponse</property> flag with
40                 <methodname>Zend_Controller_Front::returnResponse(true)</methodname>:
41             </para>
43             <programlisting language="php"><![CDATA[
44 $front->returnResponse(true);
45 $response = $front->dispatch();
47 // do some more processing, such as logging...
48 // and then send the output:
49 $response->sendResponse();
50 ]]></programlisting>
51         </note>
53         <para>
54             Developers should make use of the response object in their action
55             controllers. Instead of directly rendering output and sending
56             headers, push them to the response object:
57         </para>
59         <programlisting language="php"><![CDATA[
60 // Within an action controller action:
61 // Set a header
62 $this->getResponse()
63     ->setHeader('Content-Type', 'text/html')
64     ->appendBody($content);
65 ]]></programlisting>
67         <para>
68             By doing this, all headers get sent at once, just prior to
69             displaying the content.
70         </para>
72         <note>
73             <para>
74                 If using the action controller <link
75                     linkend="zend.controller.action.viewintegration">view
76                     integration</link>, you do not need to set the rendered view
77                 script content in the response object, as
78                 <methodname>Zend_Controller_Action::render()</methodname> does this by default.
79             </para>
80         </note>
82         <para>
83             Should an exception occur in an application, check the response object's
84             <methodname>isException()</methodname> flag, and retrieve the exception using
85             <methodname>getException()</methodname>. Additionally, one may create custom
86             response objects that redirect to error pages, log exception messages,
87             do pretty formatting of exception messages (for development
88             environments), etc.
89         </para>
91         <para>
92             You may retrieve the response object following the front controller
93             <methodname>dispatch()</methodname>, or request the front controller to return the
94             response object instead of rendering output.
95         </para>
97         <programlisting language="php"><![CDATA[
98 // retrieve post-dispatch:
99 $front->dispatch();
100 $response = $front->getResponse();
101 if ($response->isException()) {
102     // log, mail, etc...
105 // Or, have the front controller dispatch() process return it
106 $front->returnResponse(true);
107 $response = $front->dispatch();
109 // do some processing...
111 // finally, echo the response
112 $response->sendResponse();
113 ]]></programlisting>
115         <para>
116             By default, exception messages are not displayed. This behaviour may be
117             overridden by calling <methodname>renderExceptions()</methodname>, or enabling the
118             front controller to <methodname>throwExceptions()</methodname>, as shown above:
119         </para>
121         <programlisting language="php"><![CDATA[
122 $response->renderExceptions(true);
123 $front->dispatch($request, $response);
125 // or:
126 $front->returnResponse(true);
127 $response = $front->dispatch();
128 $response->renderExceptions();
129 $response->sendResponse();
131 // or:
132 $front->throwExceptions(true);
133 $front->dispatch();
134 ]]></programlisting>
135     </sect2>
137     <sect2 id="zend.controller.response.headers">
138         <title>Manipulating Headers</title>
140         <para>
141             As stated previously, one aspect of the response object's duties is
142             to collect and emit <acronym>HTTP</acronym> response headers. A variety of methods
143             exist for this:
144         </para>
146         <itemizedlist>
147             <listitem>
148                 <para>
149                     <methodname>canSendHeaders()</methodname> is used to determine if
150                     headers have already been sent. It takes an optional flag
151                     indicating whether or not to throw an exception if headers
152                     have already been sent. This can be overridden by setting
153                     the property <property>headersSentThrowsException</property> to
154                     <constant>FALSE</constant>.
155                 </para>
156             </listitem>
158             <listitem>
159                 <para>
160                     <methodname>setHeader($name, $value, $replace = false)</methodname> is
161                     used to set an individual header. By default, it does not
162                     replace existing headers of the same name in the object;
163                     however, setting <varname>$replace</varname> to <constant>TRUE</constant> will
164                     force it to do so.
165                 </para>
167                 <para>
168                     Before setting the header, it checks with
169                     <methodname>canSendHeaders()</methodname> to see if this operation is
170                     allowed at this point, and requests that an exception be
171                     thrown.
172                 </para>
173             </listitem>
175             <listitem>
176                 <para>
177                     <methodname>setRedirect($url, $code = 302)</methodname> sets an
178                     <acronym>HTTP</acronym> Location header for a redirect. If an
179                     <acronym>HTTP</acronym> status code has been provided, it will use that status
180                     code.
181                 </para>
183                 <para>
184                     Internally, it calls <methodname>setHeader()</methodname> with the
185                     <varname>$replace</varname> flag on to ensure only one such header
186                     is ever sent.
187                 </para>
188             </listitem>
190             <listitem>
191                 <para>
192                     <methodname>getHeaders()</methodname> returns an array of all headers.
193                     Each array element is an array with the keys 'name' and
194                     'value'.
195                 </para>
196             </listitem>
198             <listitem>
199                 <para>
200                     <methodname>clearHeaders()</methodname> clears all registered headers.
201                 </para>
202             </listitem>
204             <listitem>
205                 <para>
206                     <methodname>setRawHeader()</methodname> can be used to set headers that
207                     are not key and value pairs, such as an <acronym>HTTP</acronym> status header.
208                 </para>
209             </listitem>
211             <listitem>
212                 <para>
213                     <methodname>getRawHeaders()</methodname> returns any registered raw
214                     headers.
215                 </para>
216             </listitem>
218             <listitem>
219                 <para>
220                     <methodname>clearRawHeaders()</methodname> clears any registered raw
221                     headers.
222                 </para>
223             </listitem>
225             <listitem>
226                 <para>
227                     <methodname>clearAllHeaders()</methodname> clears both regular key and value
228                     headers as well as raw headers.
229                 </para>
230             </listitem>
231         </itemizedlist>
233         <para>
234             In addition to the above methods, there are accessors for setting
235             and retrieving the <acronym>HTTP</acronym> response code for the current request,
236             <methodname>setHttpResponseCode()</methodname> and
237             <methodname>getHttpResponseCode()</methodname>.
238         </para>
239     </sect2>
241     <sect2 id="zend.controller.response.namedsegments">
242         <title>Named Segments</title>
244         <para>
245             The response object has support for "named segments". This allows
246             you to segregate body content into different segments and order
247             those segments so output is returned in a specific order.
248             Internally, body content is saved as an array, and the various
249             accessor methods can be used to indicate placement and names within
250             that array.
251         </para>
253         <para>
254             As an example, you could use a <methodname>preDispatch()</methodname> hook to
255             add a header to the response object, then have the action controller
256             add body content, and a <methodname>postDispatch()</methodname> hook add a
257             footer:
258         </para>
260         <programlisting language="php"><![CDATA[
261 // Assume that this plugin class is registered with the front controller
262 class MyPlugin extends Zend_Controller_Plugin_Abstract
264     public function preDispatch(Zend_Controller_Request_Abstract $request)
265     {
266         $response = $this->getResponse();
267         $view = new Zend_View();
268         $view->setBasePath('../views/scripts');
270         $response->prepend('header', $view->render('header.phtml'));
271     }
273     public function postDispatch(Zend_Controller_Request_Abstract $request)
274     {
275         $response = $this->getResponse();
276         $view = new Zend_View();
277         $view->setBasePath('../views/scripts');
279         $response->append('footer', $view->render('footer.phtml'));
280     }
283 // a sample action controller
284 class MyController extends Zend_Controller_Action
286     public function fooAction()
287     {
288         $this->render();
289     }
291 ]]></programlisting>
293         <para>
294             In the above example, a call to <filename>/my/foo</filename> will cause the
295             final body content of the response object to have the following
296             structure:
297         </para>
299         <programlisting language="php"><![CDATA[
300 array(
301     'header'  => ..., // header content
302     'default' => ..., // body content from MyController::fooAction()
303     'footer'  => ...  // footer content
305 ]]></programlisting>
307         <para>
308             When this is rendered, it will render in the order in which elements
309             are arranged in the array.
310         </para>
312         <para>
313             A variety of methods can be used to manipulate the named segments:
314         </para>
316         <itemizedlist>
317             <listitem>
318                 <para>
319                     <methodname>setBody()</methodname> and <methodname>appendBody()</methodname>
320                     both allow you to pass a second value, <varname>$name</varname>,
321                     indicating a named segment. In each case, if you provide
322                     this, it will overwrite that specific named segment or
323                     create it if it does not exist (appending to the array by
324                     default). If no named segment is passed to
325                     <methodname>setBody()</methodname>, it resets the entire body content
326                     array. If no named segment is passed to <methodname>appendBody()</methodname>,
327                     the content is appended to the value in the 'default' name
328                     segment.
329                 </para>
330             </listitem>
332             <listitem>
333                 <para>
334                     <methodname>prepend($name, $content)</methodname> will create a segment
335                     named <varname>$name</varname> and place it at the beginning of
336                     the array. If the segment exists already, it will be removed
337                     prior to the operation (i.e., overwritten and replaced).
338                 </para>
339             </listitem>
341             <listitem>
342                 <para>
343                     <methodname>append($name, $content)</methodname> will create a segment
344                     named <varname>$name</varname> and place it at the end of
345                     the array. If the segment exists already, it will be removed
346                     prior to the operation (i.e., overwritten and replaced).
347                 </para>
348             </listitem>
350             <listitem>
351                 <para>
352                     <methodname>insert($name, $content, $parent = null, $before =
353                         false)</methodname> will create a segment named
354                     <varname>$name</varname>. If provided with a <varname>$parent</varname>
355                     segment, the new segment will be placed either before or
356                     after that segment (based on the value of
357                     <varname>$before</varname>) in the array. If the segment exists
358                     already, it will be removed prior to the operation (i.e.,
359                     overwritten and replaced).
360                 </para>
361             </listitem>
363             <listitem>
364                 <para>
365                     <methodname>clearBody($name = null)</methodname> will remove a single
366                     named segment if a <varname>$name</varname> is provided (and the
367                     entire array otherwise).
368                 </para>
369             </listitem>
371             <listitem>
372                 <para>
373                     <methodname>getBody($spec = false)</methodname> can be used to retrieve a
374                     single array segment if <varname>$spec</varname> is the name of a named
375                     segment. If <varname>$spec</varname> is <constant>FALSE</constant>, it returns
376                     a string formed by concatenating all named segments in order. If
377                     <varname>$spec</varname> is <constant>TRUE</constant>, it returns the body
378                     content array.
379                 </para>
380             </listitem>
381         </itemizedlist>
382     </sect2>
384     <sect2 id="zend.controller.response.exceptions">
385         <title>Testing for Exceptions in the Response Object</title>
387         <para>
388             As mentioned earlier, by default, exceptions caught during dispatch
389             are registered with the response object. Exceptions are registered
390             in a stack, which allows you to keep all exceptions thrown --
391             application exceptions, dispatch exceptions, plugin exceptions, etc.
392             Should you wish to check for particular exceptions or to log
393             exceptions, you'll want to use the response object's exception <acronym>API</acronym>:
394         </para>
396         <itemizedlist>
397             <listitem>
398                 <para>
399                     <methodname>setException(Exception $e)</methodname> allows you to
400                     register an exception.
401                 </para>
402             </listitem>
404             <listitem>
405                 <para>
406                     <methodname>isException()</methodname> will tell you if an exception has
407                     been registered.
408                 </para>
409             </listitem>
411             <listitem>
412                 <para>
413                     <methodname>getException()</methodname> returns the entire
414                     exception stack.
415                 </para>
416             </listitem>
418             <listitem>
419                 <para>
420                     <methodname>hasExceptionOfType($type)</methodname> allows you to
421                     determine if an exception of a particular class is in the
422                     stack.
423                 </para>
424             </listitem>
426             <listitem>
427                 <para>
428                     <methodname>hasExceptionOfMessage($message)</methodname> allows you to
429                     determine if an exception with a specific message is in the
430                     stack.
431                 </para>
432             </listitem>
434             <listitem>
435                 <para>
436                     <methodname>hasExceptionOfCode($code)</methodname> allows you to
437                     determine if an exception with a specific code is in the
438                     stack.
439                 </para>
440             </listitem>
442             <listitem>
443                 <para>
444                     <methodname>getExceptionByType($type)</methodname> allows you to
445                     retrieve all exceptions of a specific class from the stack.
446                     It will return <constant>FALSE</constant> if none are found, and an array of
447                     exceptions otherwise.
448                 </para>
449             </listitem>
451             <listitem>
452                 <para>
453                     <methodname>getExceptionByMessage($message)</methodname> allows you to
454                     retrieve all exceptions with a specific message from the stack.
455                     It will return <constant>FALSE</constant> if none are found, and an array of
456                     exceptions otherwise.
457                 </para>
458             </listitem>
460             <listitem>
461                 <para>
462                     <methodname>getExceptionByCode($code)</methodname> allows you to
463                     retrieve all exceptions with a specific code from the stack.
464                     It will return <constant>FALSE</constant> if none are found, and an array of
465                     exceptions otherwise.
466                 </para>
467             </listitem>
469             <listitem>
470                 <para>
471                     <methodname>renderExceptions($flag)</methodname> allows you to set a
472                     flag indicating whether or not exceptions should be emitted
473                     when the response is sent.
474                 </para>
475             </listitem>
476         </itemizedlist>
477     </sect2>
479     <sect2 id="zend.controller.response.subclassing">
480         <title>Subclassing the Response Object</title>
482         <para>
483             The purpose of the response object is to collect headers and content
484             from the various actions and plugins and return them to the client;
485             secondarily, it also collects any errors (exceptions) that occur in
486             order to process them, return them, or hide them from the end user.
487         </para>
489         <para>
490             The base response class is
491             <classname>Zend_Controller_Response_Abstract</classname>, and any subclass you
492             create should extend that class or one of its derivatives. The
493             various methods available have been listed in the previous sections.
494         </para>
496         <para>
497             Reasons to subclass the response object include modifying how output
498             is returned based on the request environment (e.g., not sending
499             headers for <acronym>CLI</acronym> or <acronym>PHP</acronym>-<acronym>GTK</acronym>
500             requests), adding functionality to return a final view based on content stored in named
501             segments, etc.
502         </para>
503     </sect2>
504 </sect1>
505 <!--
506 vim:se ts=4 sw=4 et: