本文实例讲述了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程序设计有所帮助。
【说明】:
本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:)!