程序员人生 网站导航

Zend Framework教程-Zend_Controller_Plugin插件

栏目:ZendFramework时间:2014-05-24 07:58:19

        通过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);        }    }}



------分隔线----------------------------
------分隔线----------------------------

最新技术推荐