Zend Framework教程-Zend_Helpers-动作助手-ActionStack,AjaxContext和ContextSwitch

来源:互联网 发布:python日期加减 编辑:程序博客网 时间:2024/05/06 19:27

以下是不常见的几个助手,知道其基本用法就可以了,用到的时候在具体查看即可。


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'头,这些动作将返回适当的响应格式。 



原创粉丝点击