Zend Framework教程之Zend_Controller_Plugin插件用法详解
本文实例讲述了zend framework教程之zend_controller_plugin插件用法。分享给大家供大家参考,具体如下:
通过zend_controller_plugin可以向前端控制器增加附加的功能。便于w一些特殊功能。以下是zend_controller_plugin的简单介绍。
zend_controller_plugin的基本实现
├── plugin
│ ├── abstract.php
│ ├── actionstack.php
│ ├── broker.php
│ ├── errorhandler.php
│ └── puthandler.php
zend_controller_plugin_abstract
abstract class zend_controller_plugin_abstract { protected $_request; protected $_response; public function setrequest(zend_controller_request_abstract $request) { $this->_request = $request; return $this; } public function getrequest() { return $this->_request; } public function setresponse(zend_controller_response_abstract $response) { $this->_response = $response; return $this; } public function getresponse() { return $this->_response; } /** * called before zend_controller_front begins evaluating the * request against its routes. * * @param zend_controller_request_abstract $request * @return void */ public function routestartup(zend_controller_request_abstract $request) {} /** * called after zend_controller_router exits. * * called after zend_controller_front exits from the router. * * @param zend_controller_request_abstract $request * @return void */ public function routeshutdown(zend_controller_request_abstract $request) {} /** * called before zend_controller_front enters its dispatch loop. * * @param zend_controller_request_abstract $request * @return void */ public function dispatchloopstartup(zend_controller_request_abstract $request) {} /** * called before an action is dispatched by zend_controller_dispatcher. * * this callback allows for proxy or filter behavior. by altering the * request and resetting its dispatched flag (via * {@link zend_controller_request_abstract::setdispatched() setdispatched(false)}), * the current action may be skipped. * * @param zend_controller_request_abstract $request * @return void */ public function predispatch(zend_controller_request_abstract $request) {} /** * called after an action is dispatched by zend_controller_dispatcher. * * this callback allows for proxy or filter behavior. by altering the * request and resetting its dispatched flag (via * {@link zend_controller_request_abstract::setdispatched() setdispatched(false)}), * a new action may be specified for dispatching. * * @param zend_controller_request_abstract $request * @return void */ public function postdispatch(zend_controller_request_abstract $request) {} /** * called before zend_controller_front exits its dispatch loop. * * @return void */ public function dispatchloopshutdown() {} }
zend_controller_plugin_abstract声明定义了zend_controller运行过程中的几个关键事件位置。用户可以通过指定的方法,对指定位置的请求和相应对象进行相关操作。
zend_controller_plugin_abstract中方法的描述如下:
routestartup() 在 zend_controller_front 向注册的 路由器 发送请求前被调用。
routeshutdown()在 路由器 完成请求的路由后被调用。
dispatchloopstartup() 在 zend_controller_front 进入其分发循环(dispatch loop)前被调用。
predispatch() 在动作由 分发器 分发前被调用。该回调方法允许代理或者过滤行为。通过修改请求和重设分发标志位(利用 zend_controller_request_abstract::setdispatched(false) )当前动作可以跳过或者被替换。
postdispatch() 在动作由 分发器 分发后被调用。该回调方法允许代理或者过滤行为。通过修改请求和重设分发标志位(利用 zend_controller_request_abstract::setdispatched(false) )可以指定新动作进行分发。
dispatchloopshutdown() 在 zend_controller_front 推出其分发循环后调用。
zend_controller_plugin提供的默认插件:
zend_controller_plugin_broker:插件经纪人,用于注册,管理自定义的zend_controller插件。具体用法,可以参考类代码。
zend_controller_plugin_actionstack:用于管理动作堆栈。具体用法,可以参考类代码。
zend_controller_plugin_errorhandler:用来处理抛出的异常。具体用法,可以参考类代码。
zend_controller_plugin_puthandler:用于处理请求操作 put 。具体用法,可以参考类代码。
zend_controller_plugin_broker
<?php /** zend_controller_plugin_abstract */ require_once 'zend/controller/plugin/abstract.php'; class zend_controller_plugin_broker extends zend_controller_plugin_abstract { protected $_plugins = array(); /** * register a plugin. * * @param zend_controller_plugin_abstract $plugin * @param int $stackindex * @return zend_controller_plugin_broker */ public function registerplugin(zend_controller_plugin_abstract $plugin, $stackindex = null) { if (false !== array_search($plugin, $this->_plugins, true)) { require_once 'zend/controller/exception.php'; throw new zend_controller_exception('plugin already registered'); } $stackindex = (int) $stackindex; if ($stackindex) { if (isset($this->_plugins[$stackindex])) { require_once 'zend/controller/exception.php'; throw new zend_controller_exception('plugin with stackindex "' . $stackindex . '" already registered'); } $this->_plugins[$stackindex] = $plugin; } else { $stackindex = count($this->_plugins); while (isset($this->_plugins[$stackindex])) { ++$stackindex; } $this->_plugins[$stackindex] = $plugin; } $request = $this->getrequest(); if ($request) { $this->_plugins[$stackindex]->setrequest($request); } $response = $this->getresponse(); if ($response) { $this->_plugins[$stackindex]->setresponse($response); } ksort($this->_plugins); return $this; } /** * unregister a plugin. * * @param string|zend_controller_plugin_abstract $plugin plugin object or class name * @return zend_controller_plugin_broker */ public function unregisterplugin($plugin) { if ($plugin instanceof zend_controller_plugin_abstract) { // given a plugin object, find it in the array $key = array_search($plugin, $this->_plugins, true); if (false === $key) { require_once 'zend/controller/exception.php'; throw new zend_controller_exception('plugin never registered.'); } unset($this->_plugins[$key]); } elseif (is_string($plugin)) { // given a plugin class, find all plugins of that class and unset them foreach ($this->_plugins as $key => $_plugin) { $type = get_class($_plugin); if ($plugin == $type) { unset($this->_plugins[$key]); } } } return $this; } /** * is a plugin of a particular class registered? * * @param string $class * @return bool */ public function hasplugin($class) { foreach ($this->_plugins as $plugin) { $type = get_class($plugin); if ($class == $type) { return true; } } return false; } /** * retrieve a plugin or plugins by class * * @param string $class class name of plugin(s) desired * @return false|zend_controller_plugin_abstract|array returns false if none found, plugin if only one found, and array of plugins if multiple plugins of same class found */ public function getplugin($class) { $found = array(); foreach ($this->_plugins as $plugin) { $type = get_class($plugin); if ($class == $type) { $found[] = $plugin; } } switch (count($found)) { case 0: return false; case 1: return $found[0]; default: return $found; } } /** * retrieve all plugins * * @return array */ public function getplugins() { return $this->_plugins; } /** * set request object, and register with each plugin * * @param zend_controller_request_abstract $request * @return zend_controller_plugin_broker */ public function setrequest(zend_controller_request_abstract $request) { $this->_request = $request; foreach ($this->_plugins as $plugin) { $plugin->setrequest($request); } return $this; } /** * get request object * * @return zend_controller_request_abstract $request */ public function getrequest() { return $this->_request; } /** * set response object * * @param zend_controller_response_abstract $response * @return zend_controller_plugin_broker */ public function setresponse(zend_controller_response_abstract $response) { $this->_response = $response; foreach ($this->_plugins as $plugin) { $plugin->setresponse($response); } return $this; } /** * get response object * * @return zend_controller_response_abstract $response */ public function getresponse() { return $this->_response; } /** * called before zend_controller_front begins evaluating the * request against its routes. * * @param zend_controller_request_abstract $request * @return void */ public function routestartup(zend_controller_request_abstract $request) { foreach ($this->_plugins as $plugin) { try { $plugin->routestartup($request); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); } } } } /** * called before zend_controller_front exits its iterations over * the route set. * * @param zend_controller_request_abstract $request * @return void */ public function routeshutdown(zend_controller_request_abstract $request) { foreach ($this->_plugins as $plugin) { try { $plugin->routeshutdown($request); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); } } } } /** * called before zend_controller_front enters its dispatch loop. * * during the dispatch loop, zend_controller_front keeps a * zend_controller_request_abstract object, and uses * zend_controller_dispatcher to dispatch the * zend_controller_request_abstract object to controllers/actions. * * @param zend_controller_request_abstract $request * @return void */ public function dispatchloopstartup(zend_controller_request_abstract $request) { foreach ($this->_plugins as $plugin) { try { $plugin->dispatchloopstartup($request); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); } } } } /** * called before an action is dispatched by zend_controller_dispatcher. * * @param zend_controller_request_abstract $request * @return void */ public function predispatch(zend_controller_request_abstract $request) { foreach ($this->_plugins as $plugin) { try { $plugin->predispatch($request); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); // skip rendering of normal dispatch give the error handler a try $this->getrequest()->setdispatched(false); } } } } /** * called after an action is dispatched by zend_controller_dispatcher. * * @param zend_controller_request_abstract $request * @return void */ public function postdispatch(zend_controller_request_abstract $request) { foreach ($this->_plugins as $plugin) { try { $plugin->postdispatch($request); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); } } } } /** * called before zend_controller_front exits its dispatch loop. * * @param zend_controller_request_abstract $request * @return void */ public function dispatchloopshutdown() { foreach ($this->_plugins as $plugin) { try { $plugin->dispatchloopshutdown(); } catch (exception $e) { if (zend_controller_front::getinstance()->throwexceptions()) { throw new zend_controller_exception($e->getmessage() . $e->gettraceasstring(), $e->getcode(), $e); } else { $this->getresponse()->setexception($e); } } } } }
zend_controller_plugin_actionstack
<?php /** zend_controller_plugin_abstract */ require_once 'zend/controller/plugin/abstract.php'; /** zend_registry */ require_once 'zend/registry.php'; class zend_controller_plugin_actionstack extends zend_controller_plugin_abstract { /** @var zend_registry */ protected $_registry; /** * registry key under which actions are stored * @var string */ protected $_registrykey = 'zend_controller_plugin_actionstack'; /** * valid keys for stack items * @var array */ protected $_validkeys = array( 'module', 'controller', 'action', 'params' ); /** * flag to determine whether request parameters are cleared between actions, or whether new parameters * are added to existing request parameters. * * @var bool */ protected $_clearrequestparams = false; /** * constructor * * @param zend_registry $registry * @param string $key * @return void */ public function __construct(zend_registry $registry = null, $key = null) { if (null === $registry) { $registry = zend_registry::getinstance(); } $this->setregistry($registry); if (null !== $key) { $this->setregistrykey($key); } else { $key = $this->getregistrykey(); } $registry[$key] = array(); } /** * set registry object * * @param zend_registry $registry * @return zend_controller_plugin_actionstack */ public function setregistry(zend_registry $registry) { $this->_registry = $registry; return $this; } /** * retrieve registry object * * @return zend_registry */ public function getregistry() { return $this->_registry; } /** * retrieve registry key * * @return string */ public function getregistrykey() { return $this->_registrykey; } /** * set registry key * * @param string $key * @return zend_controller_plugin_actionstack */ public function setregistrykey($key) { $this->_registrykey = (string) $key; return $this; } /** * set clearrequestparams flag * * @param bool $clearrequestparams * @return zend_controller_plugin_actionstack */ public function setclearrequestparams($clearrequestparams) { $this->_clearrequestparams = (bool) $clearrequestparams; return $this; } /** * retrieve clearrequestparams flag * * @return bool */ public function getclearrequestparams() { return $this->_clearrequestparams; } /** * retrieve action stack * * @return array */ public function getstack() { $registry = $this->getregistry(); $stack = $registry[$this->getregistrykey()]; return $stack; } /** * save stack to registry * * @param array $stack * @return zend_controller_plugin_actionstack */ protected function _savestack(array $stack) { $registry = $this->getregistry(); $registry[$this->getregistrykey()] = $stack; return $this; } /** * push an item onto the stack * * @param zend_controller_request_abstract $next * @return zend_controller_plugin_actionstack */ public function pushstack(zend_controller_request_abstract $next) { $stack = $this->getstack(); array_push($stack, $next); return $this->_savestack($stack); } /** * pop an item off the action stack * * @return false|zend_controller_request_abstract */ public function popstack() { $stack = $this->getstack(); if (0 == count($stack)) { return false; } $next = array_pop($stack); $this->_savestack($stack); if (!$next instanceof zend_controller_request_abstract) { require_once 'zend/controller/exception.php'; throw new zend_controller_exception('arraystack should only contain request objects'); } $action = $next->getactionname(); if (empty($action)) { return $this->popstack($stack); } $request = $this->getrequest(); $controller = $next->getcontrollername(); if (empty($controller)) { $next->setcontrollername($request->getcontrollername()); } $module = $next->getmodulename(); if (empty($module)) { $next->setmodulename($request->getmodulename()); } return $next; } /** * postdispatch() plugin hook -- check for actions in stack, and dispatch if any found * * @param zend_controller_request_abstract $request * @return void */ public function postdispatch(zend_controller_request_abstract $request) { // don't move on to next request if this is already an attempt to // forward if (!$request->isdispatched()) { return; } $this->setrequest($request); $stack = $this->getstack(); if (empty($stack)) { return; } $next = $this->popstack(); if (!$next) { return; } $this->forward($next); } /** * forward request with next action * * @param array $next * @return void */ public function forward(zend_controller_request_abstract $next) { $request = $this->getrequest(); if ($this->getclearrequestparams()) { $request->clearparams(); } $request->setmodulename($next->getmodulename()) ->setcontrollername($next->getcontrollername()) ->setactionname($next->getactionname()) ->setparams($next->getparams()) ->setdispatched(false); } }
zend_controller_plugin_errorhandler
<?php /** zend_controller_plugin_abstract */ require_once 'zend/controller/plugin/abstract.php'; class zend_controller_plugin_errorhandler extends zend_controller_plugin_abstract { /** * const - no controller exception; controller does not exist */ const exception_no_controller = 'exception_no_controller'; /** * const - no action exception; controller exists, but action does not */ const exception_no_action = 'exception_no_action'; /** * const - no route exception; no routing was possible */ const exception_no_route = 'exception_no_route'; /** * const - other exception; exceptions thrown by application controllers */ const exception_other = 'exception_other'; /** * module to use for errors; defaults to default module in dispatcher * @var string */ protected $_errormodule; /** * controller to use for errors; defaults to 'error' * @var string */ protected $_errorcontroller = 'error'; /** * action to use for errors; defaults to 'error' * @var string */ protected $_erroraction = 'error'; /** * flag; are we already inside the error handler loop? * @var bool */ protected $_isinsideerrorhandlerloop = false; /** * exception count logged at first invocation of plugin * @var int */ protected $_exceptioncountatfirstencounter = 0; /** * constructor * * options may include: * - module * - controller * - action * * @param array $options * @return void */ public function __construct(array $options = array()) { $this->seterrorhandler($options); } /** * seterrorhandler() - setup the error handling options * * @param array $options * @return zend_controller_plugin_errorhandler */ public function seterrorhandler(array $options = array()) { if (isset($options['module'])) { $this->seterrorhandlermodule($options['module']); } if (isset($options['controller'])) { $this->seterrorhandlercontroller($options['controller']); } if (isset($options['action'])) { $this->seterrorhandleraction($options['action']); } return $this; } /** * set the module name for the error handler * * @param string $module * @return zend_controller_plugin_errorhandler */ public function seterrorhandlermodule($module) { $this->_errormodule = (string) $module; return $this; } /** * retrieve the current error handler module * * @return string */ public function geterrorhandlermodule() { if (null === $this->_errormodule) { $this->_errormodule = zend_controller_front::getinstance()->getdispatcher()->getdefaultmodule(); } return $this->_errormodule; } /** * set the controller name for the error handler * * @param string $controller * @return zend_controller_plugin_errorhandler */ public function seterrorhandlercontroller($controller) { $this->_errorcontroller = (string) $controller; return $this; } /** * retrieve the current error handler controller * * @return string */ public function geterrorhandlercontroller() { return $this->_errorcontroller; } /** * set the action name for the error handler * * @param string $action * @return zend_controller_plugin_errorhandler */ public function seterrorhandleraction($action) { $this->_erroraction = (string) $action; return $this; } /** * retrieve the current error handler action * * @return string */ public function geterrorhandleraction() { return $this->_erroraction; } /** * route shutdown hook -- ccheck for router exceptions * * @param zend_controller_request_abstract $request */ public function routeshutdown(zend_controller_request_abstract $request) { $this->_handleerror($request); } /** * pre dispatch hook -- check for exceptions and dispatch error handler if * necessary * * @param zend_controller_request_abstract $request */ public function predispatch(zend_controller_request_abstract $request) { $this->_handleerror($request); } /** * post dispatch hook -- check for exceptions and dispatch error handler if * necessary * * @param zend_controller_request_abstract $request */ public function postdispatch(zend_controller_request_abstract $request) { $this->_handleerror($request); } /** * handle errors and exceptions * * if the 'noerrorhandler' front controller flag has been set, * returns early. * * @param zend_controller_request_abstract $request * @return void */ protected function _handleerror(zend_controller_request_abstract $request) { $frontcontroller = zend_controller_front::getinstance(); if ($frontcontroller->getparam('noerrorhandler')) { return; } $response = $this->getresponse(); if ($this->_isinsideerrorhandlerloop) { $exceptions = $response->getexception(); if (count($exceptions) > $this->_exceptioncountatfirstencounter) { // exception thrown by error handler; tell the front controller to throw it $frontcontroller->throwexceptions(true); throw array_pop($exceptions); } } // check for an exception and allow the error handler controller the option to forward if (($response->isexception()) && (!$this->_isinsideerrorhandlerloop)) { $this->_isinsideerrorhandlerloop = true; // get exception information $error = new arrayobject(array(), arrayobject::array_as_props); $exceptions = $response->getexception(); $exception = $exceptions[0]; $exceptiontype = get_class($exception); $error->exception = $exception; switch ($exceptiontype) { case 'zend_controller_router_exception': if (404 == $exception->getcode()) { $error->type = self::exception_no_route; } else { $error->type = self::exception_other; } break; case 'zend_controller_dispatcher_exception': $error->type = self::exception_no_controller; break; case 'zend_controller_action_exception': if (404 == $exception->getcode()) { $error->type = self::exception_no_action; } else { $error->type = self::exception_other; } break; default: $error->type = self::exception_other; break; } // keep a copy of the original request $error->request = clone $request; // get a count of the number of exceptions encountered $this->_exceptioncountatfirstencounter = count($exceptions); // forward to the error handler $request->setparam('error_handler', $error) ->setmodulename($this->geterrorhandlermodule()) ->setcontrollername($this->geterrorhandlercontroller()) ->setactionname($this->geterrorhandleraction()) ->setdispatched(false); } } }
zend_controller_plugin_puthandler
<?php require_once 'zend/controller/plugin/abstract.php'; require_once 'zend/controller/request/http.php'; class zend_controller_plugin_puthandler extends zend_controller_plugin_abstract { /** * before dispatching, digest put request body and set params * * @param zend_controller_request_abstract $request */ public function predispatch(zend_controller_request_abstract $request) { if (!$request instanceof zend_controller_request_http) { return; } if ($this->_request->isput()) { $putparams = array(); parse_str($this->_request->getrawbody(), $putparams); $request->setparams($putparams); } } }
更多关于zend相关内容感兴趣的读者可查看本站专题:《zend framework框架入门教程》、《php优秀开发框架总结》、《yii框架入门及常用技巧总结》、《thinkphp入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家php程序设计有所帮助。
推荐阅读
-
Zend Framework教程之Application用法实例详解
-
Zend Framework入门教程之Zend_Registry组件用法详解
-
Zend Framework入门教程之Zend_Config组件用法详解
-
Zend Framework教程之Zend_Controller_Plugin插件用法详解
-
Zend Framework教程之Loader以及PluginLoader用法详解
-
Zend Framework教程之Autoloading用法详解
-
Zend Framework教程之资源(Resources)用法实例详解
-
Zend Framework教程之前端控制器Zend_Controller_Front用法详解
-
Zend Framework教程之Application和Bootstrap用法详解
-
Zend Framework教程之分发器Zend_Controller_Dispatcher用法详解