Zend Framework教程-Zend_Helpers-動作助手-ActionStack,AjaxContext和ContextSwitc
來源:程序員人生 發布時間:2013-12-19 16:18:47 閱讀次數:5414次
以下是不常見的幾個助手,知道其基本用法就可以了,用到的時候在具體查看即可。
ActionStack 用于操作動作堆棧。
ContextSwitch 和 AjaxContext 為你的動作提供替代響應格式;
ActionStack
動作堆棧助手允許把請求壓到動作堆棧前端控制器插件,有效地幫助你在請求期間創建一個動作隊列來執行。(動作堆棧)助手允許你通過指定新的請求對象或通過“動作/控制器/模塊”集合來添加動作。
Note: 調用動作堆棧助手來初始化動作堆棧插件
調用動作堆棧 助手暗中注冊動作堆棧 插件 -- 這就意味著你不需要顯性地注冊動作堆棧 插件來用這個功能。
Example #1 用動作、控制器和模塊名來添加一個任務
經常地,僅僅指定動作、控制器和模塊(和可選的參數)最簡單,和調用Zend_Controller_Action::_forward()一樣:
class FooController extends Zend_Controller_Action{ public function barAction() { // Add two actions to the stack // Add call to /foo/baz/bar/baz // (FooController::bazAction() with request var bar == baz) $this->_helper->actionStack('baz', 'foo', 'default', array('bar' => 'baz')); // Add call to /bar/bat // (BarController::batAction()) $this->_helper->actionStack('bat', 'bar'); }} Example #2 使用請求對象添加一個任務有時候請求對象的OOP本性很有用;你也可以傳遞這樣一個對象給動作堆棧助手。 class FooController extends Zend_Controller_Action{ public function barAction() { // Add two actions to the stack // Add call to /foo/baz/bar/baz // (FooController::bazAction() with request var bar == baz) $request = clone $this->getRequest(); // Don't set controller or module; use current values $request->setActionName('baz') ->setParams(array('bar' => 'baz')); $this->_helper->actionStack($request); // Add call to /bar/bat // (BarController::batAction()) $request = clone $this->getRequest(); // don't set module; use current value $request->setActionName('bat') ->setControllerName('bar'); $this->_helper->actionStack($request); }}
ContextSwitch and AjaxContext
ContextSwitch 動作助手用來使在請求后返回不同的響應格式變得容易。AjaxContext 助手是 ContextSwitch 的特別版本,用來返回響應到 XmlHttpRequests。
你必須在關于動作能夠響應哪個上下文(context)的控制器中打開(enable)其中一個。如果一個進來的請求對給定的動作指出一個有效的上下文,助手將做:
如果布局被打開,則關閉它。
設置一個備用的視圖后綴,為上下文有效地請求一個分離的視圖腳本。
為期望的上下文發送適當的響應頭。
可選地調用特別的回調(callback)來設置上下文和/或執行處理后的任務。
例子,考慮下列的控制器:
class NewsController extends Zend_Controller_Action{ /** * Landing page; forwards to listAction() */ public function indexAction() { $this->_forward('list'); } /** * List news items */ public function listAction() { } /** * View a news item */ public function viewAction() { }}
我們想讓 listAction() 也支持 XML 格式,不用創建一個不同的動作,我們可以提示它可以返回 XML 響應:
class NewsController extends Zend_Controller_Action{ public function init() { $contextSwitch = $this->_helper->getHelper('contextSwitch'); $contextSwitch->addActionContext('list', 'xml') ->initContext(); } // ...}
這將完成:
設置 'Content-Type' 響應頭為 'text/xml'.
修改視圖后綴為 'xml.phtml' (或者,如果你使用另外的視圖后綴,'xml.[你的后綴]')。
現在你需要創建一個新的視圖腳本 'news/list.xml.phtml',它將創建和解析 XML。
為決定一個請求是否應該初始化一個上下文開關(context switch),這個助手檢查在請求對象理的令牌。缺省地,它尋找一個 'format' 參數,盡管這是可配置的。這意味著,在大多數情況下,為觸發一個上下文開關,你可以添加一個 'format' 參數給你的請求:
通過 URL 參數:/news/list/format/xml (回憶一下,缺省路由模式(schema)允許在動作后跟隨任意的鍵/值對)
通過 GET 參數:/news/list?format=xml
ContextSwitch 允許指定任意的上下文,包括需要修改后綴的、任何應該被發送的響應頭和任意的用來初始化和善后的回調(callback)。
缺省可用的上下文
缺省地,ContextSwitch 助手的兩個上下文可用:json 和 xml。
JSON. JSON 上下文設置 'Content-Type' 響應頭為 'application/json',設置視圖腳本后綴為 'json.phtml'。
缺省地,不需要視圖腳本,它將系列化所有的視圖變量,立即發出 JSON 響應。
通過關閉 auto-JSON serialization 可禁止這個行為:
$this->_helper->contextSwitch()->setAutoJsonSerialization(false);
XML. XML 上下文設置 'Content-Type' 響應頭為 'text/xml',設置視圖腳本后綴為 'xml.phtml'。你需要為這個上下文創建新的視圖腳本。
創建定制的上下文
有時候,缺省的上下文不夠用,例如你需要返回 YAML,或系列化 PHP、RSS 或 ATOM feed 等等,ContextSwitch 正是你需要的東西。
最容易的添加新的上下文的辦法是通過 addContext() 方法。這個方法帶有兩個參數:上下文的名稱和一個規范(specification)數組,規范應當包含下列中的一個或多個:
suffix: 當在視圖解析器里注冊時,預先準備的缺省的視圖后綴。
headers: 作為響應的一部分發送的頭/值(header/value)對的數組。
callbacks: 數組,包含一個或更多鍵 'init' 或 'post',指向有效的可用于上下文和善后處理的 PHP 回調(callback)。
回調的初始化發生在當 ContextSwitch 檢測到上下文時,你可以用它來執行任意的應該發生的邏輯。作為例子,當 auto-JSON serialization 是 on 的時候,JSON 上下文使用回調來關閉視圖解析器(ViewRenderer)。
善后處理(post processing)發生在動作的 postDispatch() 程序期間,可用來執行任意的邏輯。作為例子,JSON 上下文使用回調(callback)來決定是否 auto-JSON serialization 是 on;如果是,它系列化視圖變量到 JSON 和 發送響應,如果不是,它重新打開(re-enable)視圖解析器(ViewRenderer)。
和上下文交互作用的方法:
addContext($context, array $spec): 添加新的上下文,如果上下文存在,拋出一個異常。
setContext($context, array $spec): 添加新的上下文或重寫一個已存在的上下文,和 addContext() 使用相同的規范(specification)。
addContexts(array $contexts): 一次添加多個上下文。$contexts 應當是上下文/規范(context/specification)對的數組。如果任何一個上下文存在,就拋出異常。
setContexts(array $contexts): 添加和重寫存在的上下文(多于一個),和 addContexts() 使用相同的規范。
hasContext($context): 如果上下文存在,返回 true,否則返回 false。
getContext($context): 通過名稱來獲取一個單個的上下文,返回一個遵循用于 addContext() 的規范的數組。
getContexts(): 獲取所有的上下文,返回上下文/規范對的數組。
removeContext($context): 通過名稱來清除一個單個的上下文,成功返回 true,如果沒有發現上下文返回 false。
clearContexts(): 清除所有上下文。
為每個動作設置上下文
有兩個設置可用的上下文的機制:或者在控制器里手工創建數組,或者使用在 ContextSwitch 里的方法來裝配它們。
添加動作/上下文關系的基本方法是 addActionContext() 。它有兩個參數:上下文被添加到的動作和上下文的名稱或上下文數組的其中之一。作為例子,考慮下列的控制器類:
class FooController extends Zend_Controller_Action{ public function listAction() { } public function viewAction() { } public function commentsAction() { } public function updateAction() { }}
假如我們想添加 XML 上下文到 'list'動作、XML 和 JSON 上下文到 'comments' 動作,可以在 init() 方法中完成:
class FooController extends Zend_Controller_Action{ public function init() { $this->_helper->contextSwitch() ->addActionContext('list', 'xml') ->addActionContext('comments', array('xml', 'json')) ->initContext(); }}
另外,還可以定義數組屬性 $contexts:
class FooController extends Zend_Controller_Action{ public $contexts = array( 'list' => array('xml'), 'comments' => array('xml', 'json') ); public function init() { $this->_helper->contextSwitch()->initContext(); }}
上述不但缺少周密考慮,而且有潛在的錯誤。
下面的方法可用來構造上下文映射:
addActionContext($action, $context): 標記一個或多個可用的上下文給一個動作,如果映射已經存在,就追加到那些映射中。$context 可以是一個單個的上下文,或者是一個上下文數組。
一個上下文的 true 值將標記所有可用的上下文給動作。
一個 $context 的空值將關閉(disable)所有給定動作的上下文。
setActionContext($action, $context): 標記一個或多個上下文對動作可用,如果映射已經存在,它就替換它們。$context 可以是一個單個的上下文,或者是一個上下文數組。
addActionContexts(array $contexts): 一次性添加若干動作/上下文對,$contexts 是動作/上下文對的關聯數組。它代理 addActionContext(),意味著如果那些動作/上下文對存在,就追加之。
setActionContexts(array $contexts): 和 addActionContexts() 一樣,但重寫已存在的動作/上下文對。
hasActionContext($action, $context): 決定一個特定的動作是否有一個給定的上下文。
getActionContexts($action = null): 返回或者給定動作的所有上下文,或者所有動作/上下文對。
removeActionContext($action, $context): 從給定動作中清除一個或多個上下文。$context 可以是一個單個的上下文,或者是一個上下文數組。
clearActionContexts($action = null): 從給定動作或者從有上下文的動作中清除所有上下文。
初始化上下文開關
為初始化上下文開關,需要在動作控制器中調用 initContext():
class NewsController extends Zend_Controller_Action{ public function init() { $this->_helper->contextSwitch()->initContext(); }}
在某些情況下,你想強制使用上下文,例如,如果上下文開關是激活狀態,你只想用 XML 上下文,可以通過傳遞上下文給 initContext() 來完成:
$contextSwitch->initContext('xml');
另外的功能
用來改變 ContextSwitch 助手行為的方法包括:
setAutoJsonSerialization($flag): 缺省地,JSON 上下文將系列化任何視圖變量給 JSON 符號并把它作為響應返回。如果想創建自己的響應,你需要關閉它,這需要在調用 initContext() 之前來完成。
$contextSwitch->setAutoJsonSerialization(false);
$contextSwitch->initContext();
用 getAutoJsonSerialization() 來獲取 flag 的值。
setSuffix($context, $suffix, $prependViewRendererSuffix): 用這個方法,你可以為給定的上下文指定一個不同的后綴。第三個參數用來指示是否用新的后綴預先準備當前視圖解析器,這個 flag 缺省為打開。
傳遞空值給后綴將導致只有視圖解析器的后綴被使用。
addHeader($context, $header, $content): 為給定的上下文添加一個響應頭,$header 是頭的名稱,$content 是為這個頭傳遞的值。
每個上下文可以有多個頭,addHeader() 把另外的頭添加到頭的堆棧。
如果為上下文指定的 $header 已經存在,就拋出一個異常。
setHeader($context, $header, $content): setHeader() 和 addHeader() 一樣,但它允許重寫已經存在的上下文的頭。
addHeaders($context, array $headers): 一次性添加多個頭到給定的上下文,代理 addHeader(),如果頭已經存在,將拋出異常。$headers 是一個頭/上下文對的數組。
setHeaders($context, array $headers.): 象 addHeaders() 一樣,但代理 setHeader(),允許重寫已存在的頭。
getHeader($context, $header): 獲取給定上下文的頭的值,如果沒有發現返回 null。
removeHeader($context, $header): 清除一個單個的給定上下文的頭。
clearHeaders($context, $header): 清除所有給定上下文的頭。
setCallback($context, $trigger, $callback): 為給定的上下文在給定的觸發器設置回調(callback),觸發器或者是 'init',或者是 'post'(指明回調將被在上下文初始化時或者派遣后(postDispatch)調用)。 $callback 應當是一個有效的 PHP 回調。
setCallbacks($context, array $callbacks): 為給定的上下文設置多個回調,$callbacks 應當是觸發器/回調對。事實上,最常用的可注冊的回調有兩個:一個為初始化用的,一個是做善后處理。
getCallback($context, $trigger): 在給定的上下文中從給定的觸發器中獲取一個回調。
getCallbacks($context): 從給定的上下文獲取所有的回調,返回一個觸發器/回調對數組。
removeCallback($context, $trigger): 從給定的觸發器和上下文清除一個回調。
clearCallbacks($context): 為給定的上下文清除所有的回調。
setContextParam($name): 設置請求參數來檢查什么時候決定上下文開關是否已經請求,缺省值為 'format',但這個訪問器可以用來設置一個備用的值。
getContextParam() 用來獲取當前的值。
setAutoDisableLayout($flag): 缺省地,當上下文開關出現,布局是關閉的;這是因為一般布局將只用來返回正常的相應,對備用的(alternate)上下文沒有意義。然而,如果想使用布局(也許你對新的上下文有個布局),你可以通過傳遞一個 false 的值給 setAutoDisableLayout() 來改變它的行為。這應當 在 調用 initContext() 之前 來做。
用訪問器 getAutoDisableLayout() 來獲取這個 flag 的值。
getCurrentContext() 可用來確定什么上下文被檢測到,如果有的話。如果沒有上下文開關發生,或者在調用 initContext() 之前調用它,則返回 null。
AjaxContext 函數
AjaxContext 助手繼承 ContextSwitch,所有 ContextSwitch 函數列表對它也有效,只是有些小小的不同。
首先,它為確定上下文使用不同的動作控制器屬性 - $ajaxable。這樣你就可以對 AJAX 和 普通的 HTTP 請求使用不同的上下文。AjaxContext 的各種各樣 *ActionContext*() 方法將寫到這個屬性。
其次,由請求對象的 isXmlHttpRequest() 方法來確定,它只有在 XmlHttpRequest 出現后才觸發。這樣,如果上下文參數 ('format')在請求中傳遞,但請求沒有做成 XmlHttpRequest,不會觸發上下文開關。
第三,AjaxContext 添加另外的上下文 - HTML。在這個上下文中,為了區別這個上下文和普通的請求,它設置后綴為 'ajax.phtml'。沒有另外的頭返回。
Example #4 允許動作響應 Ajax 的請求
在下面的例子中,我們允許對動作 'view'、 'form' 和 'process' 的請求響應 AJAX 的請求。在頭兩個例子 'view' 和 'form',返回不更新頁面的 HTML 片段;在最后的例子,返回 JSON。
class CommentController extends Zend_Controller_Action{ public function init() { $ajaxContext = $this->_helper->getHelper('AjaxContext'); $ajaxContext->addActionContext('view', 'html') ->addActionContext('form', 'html') ->addActionContext('process', 'json') ->initContext(); } public function viewAction() { // Pull a single comment to view. // When AjaxContext detected, uses the comment/view.ajax.phtml // view script. } public function formAction() { // Render the "add new comment" form. // When AjaxContext detected, uses the comment/form.ajax.phtml // view script. } public function processAction() { // Process a new comment // Return the results as JSON; simply assign the results as // view variables, and JSON will be returned. }}
在客戶端,AJAX 庫將請求終點 '/comment/view'、 '/comment/form' 和 '/comment/process',并傳遞 'format' 參數:'/comment/view/format/html'、'/comment/form/format/html' 和 '/comment/process/format/json'。(或者你可以通過查詢字符串( query string) 傳遞參數,如:"?format=json")
假定你的庫傳遞 'X-Requested-With:XmlHttpRequest'頭,這些動作將返回適當的響應格式。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈