欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Zend Framework教程之Zend_Controller_Plugin插件用法详解

程序员文章站 2024-04-01 20:44:34
本文实例讲述了zend framework教程之zend_controller_plugin插件用法。分享给大家供大家参考,具体如下: 通过zend_controller...

本文实例讲述了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程序设计有所帮助。