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

前端之家收集整理的这篇文章主要介绍了Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本文实例讲述了Zend Framework教程之响应对象的封装Zend_Controller_Response用法分享给大家供大家参考,具体如下:

概述

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

Zend_Controller_Response响应对象的基本实现

PHP │ ├── Cli.PHP │ ├── Exception.PHP │ ├── Http.PHP │ └── HttpTestCase.PHP

Zend_Controller_Response_Abstract

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,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,$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

PHP;"> /** 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()。

sendResponse();

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

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

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

getResponse() ->setHeader('Content-Type','text/html') ->appendBody($content);

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

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

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

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

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():

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,$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()钩子中加入页脚。

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会使得最终响应对象中的内容呈现下面的结构:

...,// 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,$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请求中不发送消息头)增加返回存储在命名片段中内容的最终视图的功能等等。

更多关于zend相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》及《PHP常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

猜你在找的PHP相关文章