1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.controller.response">
4 <title>The Response Object</title>
6 <sect2 id="zend.controller.response.usage">
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
17 <methodname>Zend_Controller_Front::throwExceptions(true)</methodname>:
20 <programlisting language="php"><![CDATA[
21 $front->throwExceptions(true);
25 To send the response output, including headers, use
26 <methodname>sendResponse()</methodname>.
29 <programlisting language="php"><![CDATA[
30 $response->sendResponse();
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>:
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();
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:
59 <programlisting language="php"><![CDATA[
60 // Within an action controller action:
63 ->setHeader('Content-Type', 'text/html')
64 ->appendBody($content);
68 By doing this, all headers get sent at once, just prior to
69 displaying the content.
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.
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
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.
97 <programlisting language="php"><![CDATA[
98 // retrieve post-dispatch:
100 $response = $front->getResponse();
101 if ($response->isException()) {
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();
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:
121 <programlisting language="php"><![CDATA[
122 $response->renderExceptions(true);
123 $front->dispatch($request, $response);
126 $front->returnResponse(true);
127 $response = $front->dispatch();
128 $response->renderExceptions();
129 $response->sendResponse();
132 $front->throwExceptions(true);
137 <sect2 id="zend.controller.response.headers">
138 <title>Manipulating Headers</title>
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
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>.
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
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
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
184 Internally, it calls <methodname>setHeader()</methodname> with the
185 <varname>$replace</varname> flag on to ensure only one such header
192 <methodname>getHeaders()</methodname> returns an array of all headers.
193 Each array element is an array with the keys 'name' and
200 <methodname>clearHeaders()</methodname> clears all registered headers.
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.
213 <methodname>getRawHeaders()</methodname> returns any registered raw
220 <methodname>clearRawHeaders()</methodname> clears any registered raw
227 <methodname>clearAllHeaders()</methodname> clears both regular key and value
228 headers as well as raw headers.
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>.
241 <sect2 id="zend.controller.response.namedsegments">
242 <title>Named Segments</title>
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
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
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)
266 $response = $this->getResponse();
267 $view = new Zend_View();
268 $view->setBasePath('../views/scripts');
270 $response->prepend('header', $view->render('header.phtml'));
273 public function postDispatch(Zend_Controller_Request_Abstract $request)
275 $response = $this->getResponse();
276 $view = new Zend_View();
277 $view->setBasePath('../views/scripts');
279 $response->append('footer', $view->render('footer.phtml'));
283 // a sample action controller
284 class MyController extends Zend_Controller_Action
286 public function fooAction()
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
299 <programlisting language="php"><![CDATA[
301 'header' => ..., // header content
302 'default' => ..., // body content from MyController::fooAction()
303 'footer' => ... // footer content
308 When this is rendered, it will render in the order in which elements
309 are arranged in the array.
313 A variety of methods can be used to manipulate the named segments:
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
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).
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).
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).
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).
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
384 <sect2 id="zend.controller.response.exceptions">
385 <title>Testing for Exceptions in the Response Object</title>
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>:
399 <methodname>setException(Exception $e)</methodname> allows you to
400 register an exception.
406 <methodname>isException()</methodname> will tell you if an exception has
413 <methodname>getException()</methodname> returns the entire
420 <methodname>hasExceptionOfType($type)</methodname> allows you to
421 determine if an exception of a particular class is in the
428 <methodname>hasExceptionOfMessage($message)</methodname> allows you to
429 determine if an exception with a specific message is in the
436 <methodname>hasExceptionOfCode($code)</methodname> allows you to
437 determine if an exception with a specific code is in the
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.
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.
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.
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.
479 <sect2 id="zend.controller.response.subclassing">
480 <title>Subclassing the Response Object</title>
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.
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.
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