Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解

Zend Framework教程之响应对象的封装Zend_Controller_Response用法。具体如下:

概述

响应对象逻辑上是请求对象的搭档.目的在于收集消息体和/或消息头,因而可能返回大批的结果。

Zend_Controller_Response响应对象的基本实现

├── Response
│   ├── Abstract.php
│   ├── Cli.php
│   ├── Exception.php
│   ├── Http.php
│   └── HttpTestCase.php

Zend_Controller_Response_Abstract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
abstract class Zend_Controller_Response_Abstract
{
 /**
  * Body content
  * @var array
  */
 protected $_body = array();
 /**
  * Exception stack
  * @var Exception
  */
 protected $_exceptions = array();
 /**
  * Array of headers. Each header is an array with keys 'name' and 'value'
  * @var array
  */
 protected $_headers = array();
 /**
  * Array of raw headers. Each header is a single string, the entire header to emit
  * @var array
  */
 protected $_headersRaw = array();
 /**
  * HTTP response code to use in headers
  * @var int
  */
 protected $_httpResponseCode = 200;
 /**
  * Flag; is this response a redirect?
  * @var boolean
  */
 protected $_isRedirect = false;
 /**
  * Whether or not to render exceptions; off by default
  * @var boolean
  */
 protected $_renderExceptions = false;
 /**
  * Flag; if true, when header operations are called after headers have been
  * sent, an exception will be raised; otherwise, processing will continue
  * as normal. Defaults to true.
  *
  * @see canSendHeaders()
  * @var boolean
  */
 public $headersSentThrowsException = true;
 /**
  * Normalize a header name
  *
  * Normalizes a header name to X-Capitalized-Names
  *
  * @param string $name
  * @return string
  */
 protected function _normalizeHeader($name)
 {
  $filtered = str_replace(array('-', '_'), ' ', (string) $name);
  $filtered = ucwords(strtolower($filtered));
  $filtered = str_replace(' ', '-', $filtered);
  return $filtered;
 }
 /**
  * Set a header
  *
  * If $replace is true, replaces any headers already defined with that
  * $name.
  *
  * @param string $name
  * @param string $value
  * @param boolean $replace
  * @return Zend_Controller_Response_Abstract
  */
 public function setHeader($name, $value, $replace = false)
 {
  $this->canSendHeaders(true);
  $name = $this->_normalizeHeader($name);
  $value = (string) $value;
  if ($replace) {
   foreach ($this->_headers as $key => $header) {
    if ($name == $header['name']) {
     unset($this->_headers[$key]);
    }
   }
  }
  $this->_headers[] = array(
   'name' => $name,
   'value' => $value,
   'replace' => $replace
  );
  return $this;
 }
 /**
  * Set redirect URL
  *
  * Sets Location header and response code. Forces replacement of any prior
  * redirects.
  *
  * @param string $url
  * @param int $code
  * @return Zend_Controller_Response_Abstract
  */
 public function setRedirect($url, $code = 302)
 {
  $this->canSendHeaders(true);
  $this->setHeader('Location', $url, true)
    ->setHttpResponseCode($code);
  return $this;
 }
 /**
  * Is this a redirect?
  *
  * @return boolean
  */
 public function isRedirect()
 {
  return $this->_isRedirect;
 }
 /**
  * Return array of headers; see {@link $_headers} for format
  *
  * @return array
  */
 public function getHeaders()
 {
  return $this->_headers;
 }
 /**
  * Clear headers
  *
  * @return Zend_Controller_Response_Abstract
  */
 public function clearHeaders()
 {
  $this->_headers = array();
  return $this;
 }
 /**
  * Clears the specified HTTP header
  *
  * @param string $name
  * @return Zend_Controller_Response_Abstract
  */
 public function clearHeader($name)
 {
  if (! count($this->_headers)) {
   return $this;
  }
  foreach ($this->_headers as $index => $header) {
   if ($name == $header['name']) {
    unset($this->_headers[$index]);
   }
  }
  return $this;
 }
 /**
  * Set raw HTTP header
  *
  * Allows setting non key => value headers, such as status codes
  *
  * @param string $value
  * @return Zend_Controller_Response_Abstract
  */
 public function setRawHeader($value)
 {
  $this->canSendHeaders(true);
  if ('Location' == substr($value, 0, 8)) {
   $this->_isRedirect = true;
  }
  $this->_headersRaw[] = (string) $value;
  return $this;
 }
 /**
  * Retrieve all {@link setRawHeader() raw HTTP headers}
  *
  * @return array
  */
 public function getRawHeaders()
 {
  return $this->_headersRaw;
 }
 /**
  * Clear all {@link setRawHeader() raw HTTP headers}
  *
  * @return Zend_Controller_Response_Abstract
  */
 public function clearRawHeaders()
 {
  $this->_headersRaw = array();
  return $this;
 }
 /**
  * Clears the specified raw HTTP header
  *
  * @param string $headerRaw
  * @return Zend_Controller_Response_Abstract
  */
 public function clearRawHeader($headerRaw)
 {
  if (! count($this->_headersRaw)) {
   return $this;
  }
  $key = array_search($headerRaw, $this->_headersRaw);
  if ($key !== false) {
   unset($this->_headersRaw[$key]);
  }
  return $this;
 }
 /**
  * Clear all headers, normal and raw
  *
  * @return Zend_Controller_Response_Abstract
  */
 public function clearAllHeaders()
 {
  return $this->clearHeaders()
     ->clearRawHeaders();
 }
 /**
  * Set HTTP response code to use with headers
  *
  * @param int $code
  * @return Zend_Controller_Response_Abstract
  */
 public function setHttpResponseCode($code)
 {
  if (!is_int($code) || (100 > $code) || (599 < $code)) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Invalid HTTP response code');
  }
  if ((300 <= $code) && (307 >= $code)) {
   $this->_isRedirect = true;
  } else {
   $this->_isRedirect = false;
  }
  $this->_httpResponseCode = $code;
  return $this;
 }
 /**
  * Retrieve HTTP response code
  *
  * @return int
  */
 public function getHttpResponseCode()
 {
  return $this->_httpResponseCode;
 }
 /**
  * Can we send headers?
  *
  * @param boolean $throw Whether or not to throw an exception if headers have been sent; defaults to false
  * @return boolean
  * @throws Zend_Controller_Response_Exception
  */
 public function canSendHeaders($throw = false)
 {
  $ok = headers_sent($file, $line);
  if ($ok && $throw && $this->headersSentThrowsException) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
  }
  return !$ok;
 }
 /**
  * Send all headers
  *
  * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code}
  * has been specified, it is sent with the first header.
  *
  * @return Zend_Controller_Response_Abstract
  */
 public function sendHeaders()
 {
  // Only check if we can send headers if we have headers to send
  if (count($this->_headersRaw) || count($this->_headers) || (200 != $this->_httpResponseCode)) {
   $this->canSendHeaders(true);
  } elseif (200 == $this->_httpResponseCode) {
   // Haven't changed the response code, and we have no headers
   return $this;
  }
  $httpCodeSent = false;
  foreach ($this->_headersRaw as $header) {
   if (!$httpCodeSent && $this->_httpResponseCode) {
    header($header, true, $this->_httpResponseCode);
    $httpCodeSent = true;
   } else {
    header($header);
   }
  }
  foreach ($this->_headers as $header) {
   if (!$httpCodeSent && $this->_httpResponseCode) {
    header($header['name'] . ': ' . $header['value'], $header['replace'], $this->_httpResponseCode);
    $httpCodeSent = true;
   } else {
    header($header['name'] . ': ' . $header['value'], $header['replace']);
   }
  }
  if (!$httpCodeSent) {
   header('HTTP/1.1 ' . $this->_httpResponseCode);
   $httpCodeSent = true;
  }
  return $this;
 }
 /**
  * Set body content
  *
  * If $name is not passed, or is not a string, resets the entire body and
  * sets the 'default' key to $content.
  *
  * If $name is a string, sets the named segment in the body array to
  * $content.
  *
  * @param string $content
  * @param null|string $name
  * @return Zend_Controller_Response_Abstract
  */
 public function setBody($content, $name = null)
 {
  if ((null === $name) || !is_string($name)) {
   $this->_body = array('default' => (string) $content);
  } else {
   $this->_body[$name] = (string) $content;
  }
  return $this;
 }
 /**
  * Append content to the body content
  *
  * @param string $content
  * @param null|string $name
  * @return Zend_Controller_Response_Abstract
  */
 public function appendBody($content, $name = null)
 {
  if ((null === $name) || !is_string($name)) {
   if (isset($this->_body['default'])) {
    $this->_body['default'] .= (string) $content;
   } else {
    return $this->append('default', $content);
   }
  } elseif (isset($this->_body[$name])) {
   $this->_body[$name] .= (string) $content;
  } else {
   return $this->append($name, $content);
  }
  return $this;
 }
 /**
  * Clear body array
  *
  * With no arguments, clears the entire body array. Given a $name, clears
  * just that named segment; if no segment matching $name exists, returns
  * false to indicate an error.
  *
  * @param string $name Named segment to clear
  * @return boolean
  */
 public function clearBody($name = null)
 {
  if (null !== $name) {
   $name = (string) $name;
   if (isset($this->_body[$name])) {
    unset($this->_body[$name]);
    return true;
   }
   return false;
  }
  $this->_body = array();
  return true;
 }
 /**
  * Return the body content
  *
  * If $spec is false, returns the concatenated values of the body content
  * array. If $spec is boolean true, returns the body content array. If
  * $spec is a string and matches a named segment, returns the contents of
  * that segment; otherwise, returns null.
  *
  * @param boolean $spec
  * @return string|array|null
  */
 public function getBody($spec = false)
 {
  if (false === $spec) {
   ob_start();
   $this->outputBody();
   return ob_get_clean();
  } elseif (true === $spec) {
   return $this->_body;
  } elseif (is_string($spec) && isset($this->_body[$spec])) {
   return $this->_body[$spec];
  }
  return null;
 }
 /**
  * Append a named body segment to the body content array
  *
  * If segment already exists, replaces with $content and places at end of
  * array.
  *
  * @param string $name
  * @param string $content
  * @return Zend_Controller_Response_Abstract
  */
 public function append($name, $content)
 {
  if (!is_string($name)) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
  }
  if (isset($this->_body[$name])) {
   unset($this->_body[$name]);
  }
  $this->_body[$name] = (string) $content;
  return $this;
 }
 /**
  * Prepend a named body segment to the body content array
  *
  * If segment already exists, replaces with $content and places at top of
  * array.
  *
  * @param string $name
  * @param string $content
  * @return void
  */
 public function prepend($name, $content)
 {
  if (!is_string($name)) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
  }
  if (isset($this->_body[$name])) {
   unset($this->_body[$name]);
  }
  $new = array($name => (string) $content);
  $this->_body = $new + $this->_body;
  return $this;
 }
 /**
  * Insert a named segment into the body content array
  *
  * @param string $name
  * @param string $content
  * @param string $parent
  * @param boolean $before Whether to insert the new segment before or
  * after the parent. Defaults to false (after)
  * @return Zend_Controller_Response_Abstract
  */
 public function insert($name, $content, $parent = null, $before = false)
 {
  if (!is_string($name)) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
  }
  if ((null !== $parent) && !is_string($parent)) {
   require_once 'Zend/Controller/Response/Exception.php';
   throw new Zend_Controller_Response_Exception('Invalid body segment parent key ("' . gettype($parent) . '")');
  }
  if (isset($this->_body[$name])) {
   unset($this->_body[$name]);
  }
  if ((null === $parent) || !isset($this->_body[$parent])) {
   return $this->append($name, $content);
  }
  $ins = array($name => (string) $content);
  $keys = array_keys($this->_body);
  $loc = array_search($parent, $keys);
  if (!$before) {
   // Increment location if not inserting before
   ++$loc;
  }
  if (0 === $loc) {
   // If location of key is 0, we're prepending
   $this->_body = $ins + $this->_body;
  } elseif ($loc >= (count($this->_body))) {
   // If location of key is maximal, we're appending
   $this->_body = $this->_body + $ins;
  } else {
   // Otherwise, insert at location specified
   $pre = array_slice($this->_body, 0, $loc);
   $post = array_slice($this->_body, $loc);
   $this->_body = $pre + $ins + $post;
  }
  return $this;
 }
 /**
  * Echo the body segments
  *
  * @return void
  */
 public function outputBody()
 {
  $body = implode('', $this->_body);
  echo $body;
 }
 /**
  * Register an exception with the response
  *
  * @param Exception $e
  * @return Zend_Controller_Response_Abstract
  */
 public function setException(Exception $e)
 {
  $this->_exceptions[] = $e;
  return $this;
 }
 /**
  * Retrieve the exception stack
  *
  * @return array
  */
 public function getException()
 {
  return $this->_exceptions;
 }
 /**
  * Has an exception been registered with the response?
  *
  * @return boolean
  */
 public function isException()
 {
  return !empty($this->_exceptions);
 }
 /**
  * Does the response object contain an exception of a given type?
  *
  * @param string $type
  * @return boolean
  */
 public function hasExceptionOfType($type)
 {
  foreach ($this->_exceptions as $e) {
   if ($e instanceof $type) {
    return true;
   }
  }
  return false;
 }
 /**
  * Does the response object contain an exception with a given message?
  *
  * @param string $message
  * @return boolean
  */
 public function hasExceptionOfMessage($message)
 {
  foreach ($this->_exceptions as $e) {
   if ($message == $e->getMessage()) {
    return true;
   }
  }
  return false;
 }
 /**
  * Does the response object contain an exception with a given code?
  *
  * @param int $code
  * @return boolean
  */
 public function hasExceptionOfCode($code)
 {
  $code = (int) $code;
  foreach ($this->_exceptions as $e) {
   if ($code == $e->getCode()) {
    return true;
   }
  }
  return false;
 }
 /**
  * Retrieve all exceptions of a given type
  *
  * @param string $type
  * @return false|array
  */
 public function getExceptionByType($type)
 {
  $exceptions = array();
  foreach ($this->_exceptions as $e) {
   if ($e instanceof $type) {
    $exceptions[] = $e;
   }
  }
  if (empty($exceptions)) {
   $exceptions = false;
  }
  return $exceptions;
 }
 /**
  * Retrieve all exceptions of a given message
  *
  * @param string $message
  * @return false|array
  */
 public function getExceptionByMessage($message)
 {
  $exceptions = array();
  foreach ($this->_exceptions as $e) {
   if ($message == $e->getMessage()) {
    $exceptions[] = $e;
   }
  }
  if (empty($exceptions)) {
   $exceptions = false;
  }
  return $exceptions;
 }
 /**
  * Retrieve all exceptions of a given code
  *
  * @param mixed $code
  * @return void
  */
 public function getExceptionByCode($code)
 {
  $code  = (int) $code;
  $exceptions = array();
  foreach ($this->_exceptions as $e) {
   if ($code == $e->getCode()) {
    $exceptions[] = $e;
   }
  }
  if (empty($exceptions)) {
   $exceptions = false;
  }
  return $exceptions;
 }
 /**
  * Whether or not to render exceptions (off by default)
  *
  * If called with no arguments or a null argument, returns the value of the
  * flag; otherwise, sets it and returns the current value.
  *
  * @param boolean $flag Optional
  * @return boolean
  */
 public function renderExceptions($flag = null)
 {
  if (null !== $flag) {
   $this->_renderExceptions = $flag ? true : false;
  }
  return $this->_renderExceptions;
 }
 /**
  * Send the response, including all headers, rendering exceptions if so
  * requested.
  *
  * @return void
  */
 public function sendResponse()
 {
  $this->sendHeaders();
  if ($this->isException() && $this->renderExceptions()) {
   $exceptions = '';
   foreach ($this->getException() as $e) {
    $exceptions .= $e->__toString() . "n";
   }
   echo $exceptions;
   return;
  }
  $this->outputBody();
 }
 /**
  * Magic __toString functionality
  *
  * Proxies to {@link sendResponse()} and returns response value as string
  * using output buffering.
  *
  * @return string
  */
 public function __toString()
 {
  ob_start();
  $this->sendResponse();
  return ob_get_clean();
 }
}

Zend_Controller_Response_Http

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** Zend_Controller_Response_Abstract */
require_once 'Zend/Controller/Response/Abstract.php';
/**
 * Zend_Controller_Response_Http
 *
 * HTTP response for controllers
 *
 * @uses Zend_Controller_Response_Abstract
 * @package Zend_Controller
 * @subpackage Response
 */
class Zend_Controller_Response_Http extends Zend_Controller_Response_Abstract
{
}

常见使用用法

如果要发送响应输出包括消息头,使用sendResponse()。

1
$response->sendResponse();

Note: 默认地,前端控制器完成分发请求后调用sendResponse();一般地,你不需要调用它。但是,如果你想处理响应或者用它来测试你可以使用Zend_Controller_Front::returnResponse(true)设置returnResponse 标志覆盖默认行为:

1
2
3
4
5
$front->returnResponse(true);
$response = $front->dispatch();
// do some more processing, such as logging...
// and then send the output:
$response->sendResponse();

在动作控制器中使用响应对象。把结果写进响应对象,而不是直接渲染输出和发送消息头:

1
2
3
4
5
// Within an action controller action:
// Set a header
$this->getResponse()
 ->setHeader('Content-Type', 'text/html')
 ->appendBody($content);

这样做,可以在显示内容之前,将所有消息头一次发送。

Note: 如果使用动作控制器的 视图集成(view integration),你不需要在相应对象中设置渲染的视图脚本,因为Zend_Controller_Action::render() 默认完成了这些。

如果程序中发生了异常,检查响应对象的isException() 标志,使用getException()获取异常。此外,可以创建定制的响应对象重定向到错误页面,记录异常消息,漂亮的格式化异常消息等。

在前端控制器执行dispatch()后可以获得响应对象,或者请求前端控制器返回响应对象代替渲染输出。

1
2
3
4
5
6
7
8
9
10
11
12
// retrieve post-dispatch:
$front->dispatch();
$response = $front->getResponse();
if ($response->isException()) {
 // log, mail, etc...
}
// Or, have the front controller dispatch() process return it
$front->returnResponse(true);
$response = $front->dispatch();
// do some processing...
// finally, echo the response
$response->sendResponse();

默认地,异常消息是不显示的。可以通过调用renderExceptions()覆盖默认设置。或者启用前端控制器的throwExceptions():

1
2
3
4
5
6
7
8
9
10
$response->renderExceptions(true);
$front->dispatch($request, $response);
// or:
$front->returnResponse(true);
$response = $front->dispatch();
$response->renderExceptions();
$response->sendResponse();
// or:
$front->throwExceptions(true);
$front->dispatch();

处理消息头

如上文所述,响应对象的一项重要职责是收集和发出HTTP响应消息头,相应地存在大量的方法:

canSendHeaders() 用来判别消息头是否已发送,该方法带有一个可选的标志指示消息头已发出时是否抛出异常。可以通过设置headersSentThrowsException 属性为false来覆盖默认设置。
setHeader($name, $value, $replace = false)用来设置单独的消息头。默认的不会替换已经存在的同名消息头,但可以设置$replace 为true强制替换.
设置消息头前,该方法先检查canSendHeaders()看操作是否允许,并请求抛出异常。
setRedirect($url, $code = 302) 设置HTTP定位消息头准备重定向,如果提供HTTP状态码,重定向将会使用该状态码。
其内部调用setHeader()并使$replace 标志呈打开状态确保只发送一次定位消息头。
getHeaders() 返回一个消息头数组,每个元素都是一个带有’name’和’value’键的数组。
clearHeaders() 清除所有注册的键值消息头。
setRawHeader() 设置没有键值对的原始消息头,比如HTTP状态消息头。
getRawHeaders() 返回所有注册的原始消息头。
clearRawHeaders()清除所有的原始消息头。
clearAllHeaders() 清除所有的消息头,包括原始消息头和键值消息头。

除了上述方法,还有获取和设置当前请求HTTP响应码的访问器, setHttpResponseCode() 和 getHttpResponseCode().

命名片段

相应对象支持“命名片段”。允许你将消息体分割成不同的片段,并呈一定顺序排列。因此输出的是以特定次序返回的。在其内部,主体内容被存储为一个数组,大量的访问器方法可以用来指示数组内位置和名称。

举例来说,你可以使用preDispatch() 钩子来向响应对象中加入页头,然后在动作控制器中加入主体内容,最后在postDispatch()钩子中加入页脚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Assume that this plugin class is registered with the front controller
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
 public function preDispatch(Zend_Controller_Request_Abstract $request)
 {
  $response = $this->getResponse();
  $view = new Zend_View();
  $view->setBasePath('../views/scripts');
  $response->prepend('header', $view->render('header.phtml'));
 }
 public function postDispatch(Zend_Controller_Request_Abstract $request)
 {
  $response = $this->getResponse();
  $view = new Zend_View();
  $view->setBasePath('../views/scripts');
  $response->append('footer', $view->render('footer.phtml'));
 }
}
// a sample action controller
class MyController extends Zend_Controller_Action
{
 public function fooAction()
 {
  $this->render();
 }
}

上面的例子中,调用/my/foo会使得最终响应对象中的内容呈现下面的结构:

1
2
3
4
5
array(
 'header' => ..., // header content
 'default' => ..., // body content from MyController::fooAction()
 'footer' => ... // footer content
);

渲染响应时,会按照数组中元素顺序来渲染。

大量的方法可以用来处理命名片段:

setBody() 和 appendBody() 都允许传入一个$name参数,指示一个命名片段。如果提供了这个参数,将会覆盖指定的命名片段,如果该片段不存在就创建一个。如果没有传入$name参数到setBody(),将会重置整个主体内容。如果没有传入$name参数到appendBody(),内容被附加到’default’命名片段。
prepend($name, $content) 将创建一个$name命名片段并放置在数组的开始位置。如果该片段存在,将首先移除。
append($name, $content) 将创建一个$name命名片段,并放置在数组的结尾位置。 如果该片段存在,将首先移除。
insert($name, $content, $parent = null, $before = false) 将创建一个$name命名片段。如果提供$parent参数,新的片段视$before的值决定放置在
$parent的前面或者后面。如果该片段存在,将首先移除。
clearBody($name = null) 如果$name参数提供,将删除该片段,否则删除全部。
getBody($spec = false) 如果$spec参数为一个片段名称,将可以获取到该字段。若$spec参数为false,将返回字符串格式的命名片段顺序链。如果$spec参数为true,返回主体内容数组。

在响应对象中测试异常

如上文所述,默认的,分发过程中的异常发生会在响应对象中注册。异常会注册在一个堆中,允许你抛出所有异常–程序异常,分发异常,插件异常等。如果你要检查或者记录特定的异常,你可能想要使用响应对象的异常API:

setException(Exception $e) 注册一个异常。
isException() 判断该异常是否注册。
getException() 返回整个异常堆。
hasExceptionOfType($type) 判断特定类的异常是否在堆中。
hasExceptionOfMessage($message) 判断带有指定消息的异常是否在堆中。
hasExceptionOfCode($code) 判断带有指定代码的异常是否在堆中。
getExceptionByType($type) 获取堆中特定类的所有异常。如果没有则返回false,否则返回数组。
getExceptionByMessage($message) 获取堆中带有特定消息的所有异常。如果没有则返回false,否则返回数组。
getExceptionByCode($code) 获取堆中带有特定编码的所有异常。如果没有则返回false,否则返回数组。
renderExceptions($flag) 设置标志指示当发送响应时是否发送其中的异常。

自定义响应对象

响应对象的目的首先在于从大量的动作和插件中收集消息头和内容,然后返回到客户端;其次,响应对象也收集发生的任何异常,以处理或者返回这些异常,再或者对终端用户隐藏它们。

响应的基类是Zend_Controller_Response_Abstract,创建的任何子类必须继承这个类或它的衍生类。前面的章节中已经列出了大量可用的方法。

自定义响应对象的原因包括基于请求环境修改返回的内容的输出方式(例如:在CLI和PHP-GTK请求中不发送消息头)增加返回存储在命名片段中内容的最终视图的功能等等。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论