Zend Framework教程之響應(yīng)對(duì)象的封裝Zend_Controller_Response實(shí)例詳解
本文實(shí)例講述了Zend Framework教程之響應(yīng)對(duì)象的封裝Zend_Controller_Response用法。分享給大家供大家參考,具體如下:
概述
響應(yīng)對(duì)象邏輯上是請(qǐng)求對(duì)象的搭檔.目的在于收集消息體和/或消息頭,因而可能返回大批的結(jié)果。
Zend_Controller_Response響應(yīng)對(duì)象的基本實(shí)現(xiàn)
├── Response
│ ├── Abstract.php
│ ├── Cli.php
│ ├── Exception.php
│ ├── Http.php
│ └── HttpTestCase.php
Zend_Controller_Response_Abstract
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
/** 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 { }
常見(jiàn)使用用法
如果要發(fā)送響應(yīng)輸出包括消息頭,使用sendResponse()。
$response->sendResponse();
Note: 默認(rèn)地,前端控制器完成分發(fā)請(qǐng)求后調(diào)用sendResponse();一般地,你不需要調(diào)用它。但是,如果你想處理響應(yīng)或者用它來(lái)測(cè)試你可以使用Zend_Controller_Front::returnResponse(true)設(shè)置returnResponse 標(biāo)志覆蓋默認(rèn)行為:
$front->returnResponse(true); $response = $front->dispatch(); // do some more processing, such as logging... // and then send the output: $response->sendResponse();
在動(dòng)作控制器中使用響應(yīng)對(duì)象。把結(jié)果寫(xiě)進(jìn)響應(yīng)對(duì)象,而不是直接渲染輸出和發(fā)送消息頭:
// Within an action controller action: // Set a header $this->getResponse() ->setHeader('Content-Type', 'text/html') ->appendBody($content);
這樣做,可以在顯示內(nèi)容之前,將所有消息頭一次發(fā)送。
Note: 如果使用動(dòng)作控制器的 視圖集成(view integration),你不需要在相應(yīng)對(duì)象中設(shè)置渲染的視圖腳本,因?yàn)閆end_Controller_Action::render() 默認(rèn)完成了這些。
如果程序中發(fā)生了異常,檢查響應(yīng)對(duì)象的isException() 標(biāo)志,使用getException()獲取異常。此外,可以創(chuàng)建定制的響應(yīng)對(duì)象重定向到錯(cuò)誤頁(yè)面,記錄異常消息,漂亮的格式化異常消息等。
在前端控制器執(zhí)行dispatch()后可以獲得響應(yīng)對(duì)象,或者請(qǐng)求前端控制器返回響應(yīng)對(duì)象代替渲染輸出。
// 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();
默認(rèn)地,異常消息是不顯示的??梢酝ㄟ^(guò)調(diào)用renderExceptions()覆蓋默認(rèn)設(shè)置?;蛘邌⒂们岸丝刂破鞯膖hrowExceptions():
$response->renderExceptions(true); $front->dispatch($request, $response); // or: $front->returnResponse(true); $response = $front->dispatch(); $response->renderExceptions(); $response->sendResponse(); // or: $front->throwExceptions(true); $front->dispatch();
處理消息頭
如上文所述,響應(yīng)對(duì)象的一項(xiàng)重要職責(zé)是收集和發(fā)出HTTP響應(yīng)消息頭,相應(yīng)地存在大量的方法:
canSendHeaders() 用來(lái)判別消息頭是否已發(fā)送,該方法帶有一個(gè)可選的標(biāo)志指示消息頭已發(fā)出時(shí)是否拋出異常??梢酝ㄟ^(guò)設(shè)置headersSentThrowsException 屬性為false來(lái)覆蓋默認(rèn)設(shè)置。
setHeader($name, $value, $replace = false)用來(lái)設(shè)置單獨(dú)的消息頭。默認(rèn)的不會(huì)替換已經(jīng)存在的同名消息頭,但可以設(shè)置$replace 為true強(qiáng)制替換.
設(shè)置消息頭前,該方法先檢查canSendHeaders()看操作是否允許,并請(qǐng)求拋出異常。
setRedirect($url, $code = 302) 設(shè)置HTTP定位消息頭準(zhǔn)備重定向,如果提供HTTP狀態(tài)碼,重定向?qū)?huì)使用該狀態(tài)碼。
其內(nèi)部調(diào)用setHeader()并使$replace 標(biāo)志呈打開(kāi)狀態(tài)確保只發(fā)送一次定位消息頭。
getHeaders() 返回一個(gè)消息頭數(shù)組,每個(gè)元素都是一個(gè)帶有'name'和'value'鍵的數(shù)組。
clearHeaders() 清除所有注冊(cè)的鍵值消息頭。
setRawHeader() 設(shè)置沒(méi)有鍵值對(duì)的原始消息頭,比如HTTP狀態(tài)消息頭。
getRawHeaders() 返回所有注冊(cè)的原始消息頭。
clearRawHeaders()清除所有的原始消息頭。
clearAllHeaders() 清除所有的消息頭,包括原始消息頭和鍵值消息頭。
除了上述方法,還有獲取和設(shè)置當(dāng)前請(qǐng)求HTTP響應(yīng)碼的訪問(wèn)器, setHttpResponseCode() 和 getHttpResponseCode().
命名片段
相應(yīng)對(duì)象支持“命名片段”。允許你將消息體分割成不同的片段,并呈一定順序排列。因此輸出的是以特定次序返回的。在其內(nèi)部,主體內(nèi)容被存儲(chǔ)為一個(gè)數(shù)組,大量的訪問(wèn)器方法可以用來(lái)指示數(shù)組內(nèi)位置和名稱。
舉例來(lái)說(shuō),你可以使用preDispatch() 鉤子來(lái)向響應(yīng)對(duì)象中加入頁(yè)頭,然后在動(dòng)作控制器中加入主體內(nèi)容,最后在postDispatch()鉤子中加入頁(yè)腳。
// 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(); } }
上面的例子中,調(diào)用/my/foo會(huì)使得最終響應(yīng)對(duì)象中的內(nèi)容呈現(xiàn)下面的結(jié)構(gòu):
array( 'header' => ..., // header content 'default' => ..., // body content from MyController::fooAction() 'footer' => ... // footer content );
渲染響應(yīng)時(shí),會(huì)按照數(shù)組中元素順序來(lái)渲染。
大量的方法可以用來(lái)處理命名片段:
setBody() 和 appendBody() 都允許傳入一個(gè)$name參數(shù),指示一個(gè)命名片段。如果提供了這個(gè)參數(shù),將會(huì)覆蓋指定的命名片段,如果該片段不存在就創(chuàng)建一個(gè)。如果沒(méi)有傳入$name參數(shù)到setBody(),將會(huì)重置整個(gè)主體內(nèi)容。如果沒(méi)有傳入$name參數(shù)到appendBody(),內(nèi)容被附加到'default'命名片段。
prepend($name, $content) 將創(chuàng)建一個(gè)$name命名片段并放置在數(shù)組的開(kāi)始位置。如果該片段存在,將首先移除。
append($name, $content) 將創(chuàng)建一個(gè)$name命名片段,并放置在數(shù)組的結(jié)尾位置。 如果該片段存在,將首先移除。
insert($name, $content, $parent = null, $before = false) 將創(chuàng)建一個(gè)$name命名片段。如果提供$parent參數(shù),新的片段視$before的值決定放置在
$parent的前面或者后面。如果該片段存在,將首先移除。
clearBody($name = null) 如果$name參數(shù)提供,將刪除該片段,否則刪除全部。
getBody($spec = false) 如果$spec參數(shù)為一個(gè)片段名稱,將可以獲取到該字段。若$spec參數(shù)為false,將返回字符串格式的命名片段順序鏈。如果$spec參數(shù)為true,返回主體內(nèi)容數(shù)組。
在響應(yīng)對(duì)象中測(cè)試異常
如上文所述,默認(rèn)的,分發(fā)過(guò)程中的異常發(fā)生會(huì)在響應(yīng)對(duì)象中注冊(cè)。異常會(huì)注冊(cè)在一個(gè)堆中,允許你拋出所有異常--程序異常,分發(fā)異常,插件異常等。如果你要檢查或者記錄特定的異常,你可能想要使用響應(yīng)對(duì)象的異常API:
setException(Exception $e) 注冊(cè)一個(gè)異常。
isException() 判斷該異常是否注冊(cè)。
getException() 返回整個(gè)異常堆。
hasExceptionOfType($type) 判斷特定類的異常是否在堆中。
hasExceptionOfMessage($message) 判斷帶有指定消息的異常是否在堆中。
hasExceptionOfCode($code) 判斷帶有指定代碼的異常是否在堆中。
getExceptionByType($type) 獲取堆中特定類的所有異常。如果沒(méi)有則返回false,否則返回?cái)?shù)組。
getExceptionByMessage($message) 獲取堆中帶有特定消息的所有異常。如果沒(méi)有則返回false,否則返回?cái)?shù)組。
getExceptionByCode($code) 獲取堆中帶有特定編碼的所有異常。如果沒(méi)有則返回false,否則返回?cái)?shù)組。
renderExceptions($flag) 設(shè)置標(biāo)志指示當(dāng)發(fā)送響應(yīng)時(shí)是否發(fā)送其中的異常。
自定義響應(yīng)對(duì)象
響應(yīng)對(duì)象的目的首先在于從大量的動(dòng)作和插件中收集消息頭和內(nèi)容,然后返回到客戶端;其次,響應(yīng)對(duì)象也收集發(fā)生的任何異常,以處理或者返回這些異常,再或者對(duì)終端用戶隱藏它們。
響應(yīng)的基類是Zend_Controller_Response_Abstract,創(chuàng)建的任何子類必須繼承這個(gè)類或它的衍生類。前面的章節(jié)中已經(jīng)列出了大量可用的方法。
自定義響應(yīng)對(duì)象的原因包括基于請(qǐng)求環(huán)境修改返回的內(nèi)容的輸出方式(例如:在CLI和PHP-GTK請(qǐng)求中不發(fā)送消息頭)增加返回存儲(chǔ)在命名片段中內(nèi)容的最終視圖的功能等等。
更多關(guān)于zend相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Zend FrameWork框架入門(mén)教程》、《php優(yōu)秀開(kāi)發(fā)框架總結(jié)》、《Yii框架入門(mén)及常用技巧總結(jié)》、《ThinkPHP入門(mén)教程》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- Zend的Registry機(jī)制的使用說(shuō)明
- Zend Framework教程之請(qǐng)求對(duì)象的封裝Zend_Controller_Request實(shí)例詳解
- zend api擴(kuò)展的php對(duì)象的autoload工具
- Zend Framework實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)的方法
- Zend Framework框架Smarty擴(kuò)展實(shí)現(xiàn)方法
- Zend Framework框架路由機(jī)制代碼分析
- Zend Framework實(shí)現(xiàn)留言本分頁(yè)功能(附demo源碼下載)
- Zend Framework實(shí)現(xiàn)具有基本功能的留言本(附demo源碼下載)
- Zend Framework實(shí)現(xiàn)將session存儲(chǔ)在memcache中的方法
- Zend Framework分頁(yè)類用法詳解
- Zend Framework入門(mén)之環(huán)境配置及第一個(gè)Hello World示例(附demo源碼下載)
- Zend Framework入門(mén)知識(shí)點(diǎn)小結(jié)
- Zend Framework緩存Cache用法簡(jiǎn)單實(shí)例
- Zend Framework教程之Zend_Registry對(duì)象用法分析
相關(guān)文章
Laravel第三方包報(bào)class not found的解決方法
今天小編就為大家分享一篇Laravel第三方包報(bào)class not found的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10destoon切換城市后實(shí)現(xiàn)logo旁邊顯示地區(qū)名稱的方法
這篇文章主要介紹了destoon切換城市后實(shí)現(xiàn)logo旁邊顯示地區(qū)名稱的方法,針對(duì)不同城市建設(shè)分站的時(shí)候很適用,需要的朋友可以參考下2014-08-08關(guān)于PHP5.6+版本“No input file specified”問(wèn)題的解決
這篇文章主要介紹了關(guān)于PHP5.6+版本“No input file specified”問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12laravel 5.4中實(shí)現(xiàn)無(wú)限級(jí)分類的方法示例
最近在工作中遇到一個(gè)需求,是要在laravel 5.4中實(shí)現(xiàn)無(wú)限級(jí)分類,但發(fā)現(xiàn)網(wǎng)上這個(gè)的資料較少,所以只能自己來(lái)實(shí)現(xiàn)了,下面這篇文章主要給大家介紹了關(guān)于在laravel 5.4中實(shí)現(xiàn)無(wú)限級(jí)分類的方法示例,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-07-07