程序员人生 网站导航

Zend Framework教程-Zend_Controller_Dispatcher分发器

栏目:ZendFramework时间:2013-11-18 15:21:08

分发器的具体实现 

Zend Framework的分发器Zend_Controller_Dispatcher设计主要有,如下类和接口组成:

├── Dispatcher│   ├── Abstract.php│   ├── Exception.php│   ├── Interface.php│   └── Standard.php

Zend_Controller_Dispatcher_Interface

定义了分发器提供的基本和标准功能。 

interface Zend_Controller_Dispatcher_Interface{    public function formatControllerName($unformatted);    public function formatModuleName($unformatted);    public function formatActionName($unformatted);    public function isDispatchable(Zend_Controller_Request_Abstract $request);    public function setParam($name, $value);    public function setParams(array $params);    public function getParam($name);    public function getParams();    public function clearParams($name = null);    public function setResponse(Zend_Controller_Response_Abstract $response = null);    public function getResponse();    public function addControllerDirectory($path, $args = null);    public function setControllerDirectory($path);    public function getControllerDirectory();    public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response);    public function isValidModule($module);    public function getDefaultModule();    public function getDefaultControllerName();    public function getDefaultAction();}

Zend_Controller_Dispatcher_Abstract

实现了Zend_Controller_Dispatcher_Interface接口,提供了分发器提供的基本和标准功能的抽象父类。 

<?php/** Zend_Controller_Dispatcher_Interface */require_once 'Zend/Controller/Dispatcher/Interface.php';abstract class Zend_Controller_Dispatcher_Abstract implements Zend_Controller_Dispatcher_Interface{    protected $_defaultAction = 'index';    protected $_defaultController = 'index';    protected $_defaultModule = 'default';    protected $_frontController;    protected $_invokeParams = array();    protected $_pathDelimiter = '_';    protected $_response = null;    protected $_wordDelimiter = array('-', '.');    public function __construct(array $params = array())    {        $this->setParams($params);    }    public function formatControllerName($unformatted)    {        return ucfirst($this->_formatName($unformatted)) . 'Controller';    }    public function formatActionName($unformatted)    {        $formatted = $this->_formatName($unformatted, true);        return strtolower(substr($formatted, 0, 1)) . substr($formatted, 1) . 'Action';    }    public function _verifyDelimiter($spec)    {        if (is_string($spec)) {            return (array) $spec;        } elseif (is_array($spec)) {            $allStrings = true;            foreach ($spec as $delim) {                if (!is_string($delim)) {                    $allStrings = false;                    break;                }            }            if (!$allStrings) {                require_once 'Zend/Controller/Dispatcher/Exception.php';                throw new Zend_Controller_Dispatcher_Exception('Word delimiter array must contain only strings');            }            return $spec;        }        require_once 'Zend/Controller/Dispatcher/Exception.php';        throw new Zend_Controller_Dispatcher_Exception('Invalid word delimiter');    }    public function getWordDelimiter()    {        return $this->_wordDelimiter;    }    public function setWordDelimiter($spec)    {        $spec = $this->_verifyDelimiter($spec);        $this->_wordDelimiter = $spec;        return $this;    }    public function getPathDelimiter()    {        return $this->_pathDelimiter;    }    public function setPathDelimiter($spec)    {        if (!is_string($spec)) {            require_once 'Zend/Controller/Dispatcher/Exception.php';            throw new Zend_Controller_Dispatcher_Exception('Invalid path delimiter');        }        $this->_pathDelimiter = $spec;        return $this;    }    protected function _formatName($unformatted, $isAction = false)    {        // preserve directories        if (!$isAction) {            $segments = explode($this->getPathDelimiter(), $unformatted);        } else {            $segments = (array) $unformatted;        }        foreach ($segments as $key => $segment) {            $segment        = str_replace($this->getWordDelimiter(), ' ', strtolower($segment));            $segment        = preg_replace('/[^a-z0-9 ]/', '', $segment);            $segments[$key] = str_replace(' ', '', ucwords($segment));        }        return implode('_', $segments);    }    public function getFrontController()    {        if (null === $this->_frontController) {            require_once 'Zend/Controller/Front.php';            $this->_frontController = Zend_Controller_Front::getInstance();        }        return $this->_frontController;    }    public function setFrontController(Zend_Controller_Front $controller)    {        $this->_frontController = $controller;        return $this;    }    public function setParam($name, $value)    {        $name = (string) $name;        $this->_invokeParams[$name] = $value;        return $this;    }    public function setParams(array $params)    {        $this->_invokeParams = array_merge($this->_invokeParams, $params);        return $this;    }    public function getParam($name)    {        if(isset($this->_invokeParams[$name])) {            return $this->_invokeParams[$name];        }        return null;    }    public function getParams()    {        return $this->_invokeParams;    }    public function clearParams($name = null)    {        if (null === $name) {            $this->_invokeParams = array();        } elseif (is_string($name) && isset($this->_invokeParams[$name])) {            unset($this->_invokeParams[$name]);        } elseif (is_array($name)) {            foreach ($name as $key) {                if (is_string($key) && isset($this->_invokeParams[$key])) {                    unset($this->_invokeParams[$key]);                }            }        }        return $this;    }    public function setResponse(Zend_Controller_Response_Abstract $response = null)    {        $this->_response = $response;        return $this;    }    public function getResponse()    {        return $this->_response;    }    public function setDefaultControllerName($controller)    {        $this->_defaultController = (string) $controller;        return $this;    }    public function getDefaultControllerName()    {        return $this->_defaultController;    }    public function setDefaultAction($action)    {        $this->_defaultAction = (string) $action;        return $this;    }    public function getDefaultAction()    {        return $this->_defaultAction;    }    public function setDefaultModule($module)    {        $this->_defaultModule = (string) $module;        return $this;    }    public function getDefaultModule()    {        return $this->_defaultModule;    }}

Zend_Controller_Dispatcher_Standard

ZendFramework继承抽象类Zend_Controller_Dispatcher_Abstract,定义了Zend_Controller_Dispatcher_Standard。Zend_Controller_Dispatcher_Standard是ZendFramework提供的基本的分发器,完成了分发功能。

<?php/** Zend_Loader */require_once 'Zend/Loader.php';/** Zend_Controller_Dispatcher_Abstract */require_once 'Zend/Controller/Dispatcher/Abstract.php';class Zend_Controller_Dispatcher_Standard extends Zend_Controller_Dispatcher_Abstract{    protected $_curDirectory;    protected $_curModule;    protected $_controllerDirectory = array();    public function __construct(array $params = array())    {        parent::__construct($params);        $this->_curModule = $this->getDefaultModule();    }    public function addControllerDirectory($path, $module = null)    {        if (null === $module) {            $module = $this->_defaultModule;        }        $module = (string) $module;        $path   = rtrim((string) $path, '/');        $this->_controllerDirectory[$module] = $path;        return $this;    }    public function setControllerDirectory($directory, $module = null)    {        $this->_controllerDirectory = array();        if (is_string($directory)) {            $this->addControllerDirectory($directory, $module);        } elseif (is_array($directory)) {            foreach ((array) $directory as $module => $path) {                $this->addControllerDirectory($path, $module);            }        } else {            require_once 'Zend/Controller/Exception.php';            throw new Zend_Controller_Exception('Controller directory spec must be either a string or an array');        }        return $this;    }    public function getControllerDirectory($module = null)    {        if (null === $module) {            return $this->_controllerDirectory;        }        $module = (string) $module;        if (array_key_exists($module, $this->_controllerDirectory)) {            return $this->_controllerDirectory[$module];        }        return null;    }    public function removeControllerDirectory($module)    {        $module = (string) $module;        if (array_key_exists($module, $this->_controllerDirectory)) {            unset($this->_controllerDirectory[$module]);            return true;        }        return false;    }    public function formatModuleName($unformatted)    {        if (($this->_defaultModule == $unformatted) && !$this->getParam('prefixDefaultModule')) {            return $unformatted;        }        return ucfirst($this->_formatName($unformatted));    }    public function formatClassName($moduleName, $className)    {        return $this->formatModuleName($moduleName) . '_' . $className;    }    public function classToFilename($class)    {        return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';    }    public function isDispatchable(Zend_Controller_Request_Abstract $request)    {        $className = $this->getControllerClass($request);        if (!$className) {            return false;        }        $finalClass  = $className;        if (($this->_defaultModule != $this->_curModule)            || $this->getParam('prefixDefaultModule'))        {            $finalClass = $this->formatClassName($this->_curModule, $className);        }        if (class_exists($finalClass, false)) {            return true;        }        $fileSpec    = $this->classToFilename($className);        $dispatchDir = $this->getDispatchDirectory();        $test        = $dispatchDir . DIRECTORY_SEPARATOR . $fileSpec;        return Zend_Loader::isReadable($test);    }    public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)    {        $this->setResponse($response);        /**         * Get controller class         */        if (!$this->isDispatchable($request)) {            $controller = $request->getControllerName();            if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) {                require_once 'Zend/Controller/Dispatcher/Exception.php';                throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')');            }            $className = $this->getDefaultControllerClass($request);        } else {            $className = $this->getControllerClass($request);            if (!$className) {                $className = $this->getDefaultControllerClass($request);            }        }        /**         * Load the controller class file         */        $className = $this->loadClass($className);        /**         * Instantiate controller with request, response, and invocation         * arguments; throw exception if it's not an action controller         */        $controller = new $className($request, $this->getResponse(), $this->getParams());        if (!($controller instanceof Zend_Controller_Action_Interface) &&            !($controller instanceof Zend_Controller_Action)) {            require_once 'Zend/Controller/Dispatcher/Exception.php';            throw new Zend_Controller_Dispatcher_Exception(                'Controller "' . $className . '" is not an instance of Zend_Controller_Action_Interface'            );        }        /**         * Retrieve the action name         */        $action = $this->getActionMethod($request);        /**         * Dispatch the method call         */        $request->setDispatched(true);        // by default, buffer output        $disableOb = $this->getParam('disableOutputBuffering');        $obLevel   = ob_get_level();        if (empty($disableOb)) {            ob_start();        }        try {            $controller->dispatch($action);        } catch (Exception $e) {            // Clean output buffer on error            $curObLevel = ob_get_level();            if ($curObLevel > $obLevel) {                do {                    ob_get_clean();                    $curObLevel = ob_get_level();                } while ($curObLevel > $obLevel);            }            throw $e;        }        if (empty($disableOb)) {            $content = ob_get_clean();            $response->appendBody($content);        }        // Destroy the page controller instance and reflection objects        $controller = null;    }    public function loadClass($className)    {        $finalClass  = $className;        if (($this->_defaultModule != $this->_curModule)            || $this->getParam('prefixDefaultModule'))        {            $finalClass = $this->formatClassName($this->_curModule, $className);        }        if (class_exists($finalClass, false)) {            return $finalClass;        }        $dispatchDir = $this->getDispatchDirectory();        $loadFile    = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className);        if (Zend_Loader::isReadable($loadFile)) {            include_once $loadFile;        } else {            require_once 'Zend/Controller/Dispatcher/Exception.php';            throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $loadFile . "'");        }        if (!class_exists($finalClass, false)) {            require_once 'Zend/Controller/Dispatcher/Exception.php';            throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $finalClass . '")');        }        return $finalClass;    }    public function getControllerClass(Zend_Controller_Request_Abstract $request)    {        $controllerName = $request->getControllerName();        if (empty($controllerName)) {            if (!$this->getParam('useDefaultControllerAlways')) {                return false;            }            $controllerName = $this->getDefaultControllerName();            $request->setControllerName($controllerName);        }        $className = $this->formatControllerName($controllerName);        $controllerDirs      = $this->getControllerDirectory();        $module = $request->getModuleName();        if ($this->isValidModule($module)) {            $this->_curModule    = $module;            $this->_curDirectory = $controllerDirs[$module];        } elseif ($this->isValidModule($this->_defaultModule)) {            $request->setModuleName($this->_defaultModule);            $this->_curModule    = $this->_defaultModule;            $this->_curDirectory = $controllerDirs[$this->_defaultModule];        } else {            require_once 'Zend/Controller/Exception.php';            throw new Zend_Controller_Exception('No default module defined for this application');        }        return $className;    }    public function isValidModule($module)    {        if (!is_string($module)) {            return false;        }        $module        = strtolower($module);        $controllerDir = $this->getControllerDirectory();        foreach (array_keys($controllerDir) as $moduleName) {            if ($module == strtolower($moduleName)) {                return true;            }        }        return false;    }    public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request)    {        $controller = $this->getDefaultControllerName();        $default    = $this->formatControllerName($controller);        $request->setControllerName($controller)                ->setActionName(null);        $module              = $request->getModuleName();        $controllerDirs      = $this->getControllerDirectory();        $this->_curModule    = $this->_defaultModule;        $this->_curDirectory = $controllerDirs[$this->_defaultModule];        if ($this->isValidModule($module)) {            $found = false;            if (class_exists($default, false)) {                $found = true;            } else {                $moduleDir = $controllerDirs[$module];                $fileSpec  = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default);                if (Zend_Loader::isReadable($fileSpec)) {                    $found = true;                    $this->_curDirectory = $moduleDir;                }            }            if ($found) {                $request->setModuleName($module);                $this->_curModule    = $this->formatModuleName($module);            }        } else {            $request->setModuleName($this->_defaultModule);        }        return $default;    }    public function getDispatchDirectory()    {        return $this->_curDirectory;    }    public function getActionMethod(Zend_Controller_Request_Abstract $request)    {        $action = $request->getActionName();        if (empty($action)) {            $action = $this->getDefaultAction();            $request->setActionName($action);        }        return $this->formatActionName($action);    }}

前端控制器和分发器


<?php/** Zend_Loader */require_once 'Zend/Loader.php';/** Zend_Controller_Action_HelperBroker */require_once 'Zend/Controller/Action/HelperBroker.php';/** Zend_Controller_Plugin_Broker */require_once 'Zend/Controller/Plugin/Broker.php';class Zend_Controller_Front{    protected $_baseUrl = null;    protected $_controllerDir = null;    protected $_dispatcher = null;    protected static $_instance = null;    protected $_invokeParams = array();    protected $_moduleControllerDirectoryName = 'controllers';    protected $_plugins = null;    protected $_request = null;    protected $_response = null;    protected $_returnResponse = false;    protected $_router = null;    protected $_throwExceptions = false;    protected function __construct()    {        $this->_plugins = new Zend_Controller_Plugin_Broker();    }    private function __clone()    {    }    public static function getInstance()    {        if (null === self::$_instance) {            self::$_instance = new self();        }        return self::$_instance;    }    public function resetInstance()    {        $reflection = new ReflectionObject($this);        foreach ($reflection->getProperties() as $property) {            $name = $property->getName();            switch ($name) {                case '_instance':                    break;                case '_controllerDir':                case '_invokeParams':                    $this->{$name} = array();                    break;                case '_plugins':                    $this->{$name} = new Zend_Controller_Plugin_Broker();                    break;                case '_throwExceptions':                case '_returnResponse':                    $this->{$name} = false;                    break;                case '_moduleControllerDirectoryName':                    $this->{$name} = 'controllers';                    break;                default:                    $this->{$name} = null;                    break;            }        }        Zend_Controller_Action_HelperBroker::resetHelpers();    }    public static function run($controllerDirectory)    {        self::getInstance()            ->setControllerDirectory($controllerDirectory)            ->dispatch();    }    public function addControllerDirectory($directory, $module = null)    {        $this->getDispatcher()->addControllerDirectory($directory, $module);        return $this;    }    public function setControllerDirectory($directory, $module = null)    {        $this->getDispatcher()->setControllerDirectory($directory, $module);        return $this;    }    public function getControllerDirectory($name = null)    {        return $this->getDispatcher()->getControllerDirectory($name);    }    public function removeControllerDirectory($module)    {        return $this->getDispatcher()->removeControllerDirectory($module);    }    public function addModuleDirectory($path)    {        try{            $dir = new DirectoryIterator($path);        } catch(Exception $e) {            require_once 'Zend/Controller/Exception.php';            throw new Zend_Controller_Exception("Directory $path not readable", 0, $e);        }        foreach ($dir as $file) {            if ($file->isDot() || !$file->isDir()) {                continue;            }            $module    = $file->getFilename();            // Don't use SCCS directories as modules            if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) {                continue;            }            $moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName();            $this->addControllerDirectory($moduleDir, $module);        }        return $this;    }    public function getModuleDirectory($module = null)    {        if (null === $module) {            $request = $this->getRequest();            if (null !== $request) {                $module = $this->getRequest()->getModuleName();            }            if (empty($module)) {                $module = $this->getDispatcher()->getDefaultModule();            }        }        $controllerDir = $this->getControllerDirectory($module);        if ((null === $controllerDir) || !is_string($controllerDir)) {            return null;        }        return dirname($controllerDir);    }    public function setModuleControllerDirectoryName($name = 'controllers')    {        $this->_moduleControllerDirectoryName = (string) $name;        return $this;    }    public function getModuleControllerDirectoryName()    {        return $this->_moduleControllerDirectoryName;    }    public function setDefaultControllerName($controller)    {        $dispatcher = $this->getDispatcher();        $dispatcher->setDefaultControllerName($controller);        return $this;    }    public function getDefaultControllerName()    {        return $this->getDispatcher()->getDefaultControllerName();    }    public function setDefaultAction($action)    {        $dispatcher = $this->getDispatcher();        $dispatcher->setDefaultAction($action);        return $this;    }    public function getDefaultAction()    {        return $this->getDispatcher()->getDefaultAction();    }    public function setDefaultModule($module)    {        $dispatcher = $this->getDispatcher();        $dispatcher->setDefaultModule($module);        return $this;    }    public function getDefaultModule()    {        return $this->getDispatcher()->getDefaultModule();    }    public function setRequest($request)    {                ...........................        return $this;    }     public function getRequest()    {        return $this->_request;    }     public function setRouter($router)    {        ....................        return $this;    }     public function getRouter()    {       ..................        return $this->_router;    }    public function setBaseUrl($base = null)    {       ..............        return $this;    }    public function getBaseUrl()    {         return $this->_baseUrl;    }    /**     * Set the dispatcher object.  The dispatcher is responsible for     * taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and     * call the action method of the controller.     *     * @param Zend_Controller_Dispatcher_Interface $dispatcher     * @return Zend_Controller_Front     */    public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher)    {        $this->_dispatcher = $dispatcher;        return $this;    }    /**     * Return the dispatcher object.     *     * @return Zend_Controller_Dispatcher_Interface     */    public function getDispatcher()    {        /**         * Instantiate the default dispatcher if one was not set.         */        if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) {            require_once 'Zend/Controller/Dispatcher/Standard.php';            $this->_dispatcher = new Zend_Controller_Dispatcher_Standard();        }        return $this->_dispatcher;    }     public function setResponse($response)    {..................        return $this;    }     public function getResponse()    {        return $this->_response;    }     public function setParam($name, $value)    {        $name = (string) $name;        $this->_invokeParams[$name] = $value;        return $this;    }     public function setParams(array $params)    {        $this->_invokeParams = array_merge($this->_invokeParams, $params);        return $this;    }     public function getParam($name)    {        if(isset($this->_invokeParams[$name])) {            return $this->_invokeParams[$name];        }        return null;    }     public function getParams()    {        return $this->_invokeParams;    }     public function clearParams($name = null)    {        if (null === $name) {            $this->_invokeParams = array();        } elseif (is_string($name) && isset($this->_invokeParams[$name])) {            unset($this->_invokeParams[$name]);        } elseif (is_array($name)) {            foreach ($name as $key) {                if (is_string($key) && isset($this->_invokeParams[$key])) {                    unset($this->_invokeParams[$key]);                }            }        }        return $this;    }     public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)    {        $this->_plugins->registerPlugin($plugin, $stackIndex);        return $this;    }     public function unregisterPlugin($plugin)    {        $this->_plugins->unregisterPlugin($plugin);        return $this;    }     public function hasPlugin($class)    {        return $this->_plugins->hasPlugin($class);    }     public function getPlugin($class)    {        return $this->_plugins->getPlugin($class);    }     public function getPlugins()    {        return $this->_plugins->getPlugins();    }     public function throwExceptions($flag = null)    {        .....................        return $this->_throwExceptions;    }     public function returnResponse($flag = null)    {        ................        return $this->_returnResponse;    }    /**     * Dispatch an HTTP request to a controller/action.     *     * @param Zend_Controller_Request_Abstract|null $request     * @param Zend_Controller_Response_Abstract|null $response     * @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true     */    public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)    {        if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) {            // Register with stack index of 100            require_once 'Zend/Controller/Plugin/ErrorHandler.php';            $this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100);        }        if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) {            require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';            Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer());        }        /**         * Instantiate default request object (HTTP version) if none provided         */        if (null !== $request) {            $this->setRequest($request);        } elseif ((null === $request) && (null === ($request = $this->getRequest()))) {            require_once 'Zend/Controller/Request/Http.php';            $request = new Zend_Controller_Request_Http();            $this->setRequest($request);        }        /**         * Set base URL of request object, if available         */        if (is_callable(array($this->_request, 'setBaseUrl'))) {            if (null !== $this->_baseUrl) {                $this->_request->setBaseUrl($this->_baseUrl);            }        }        /**         * Instantiate default response object (HTTP version) if none provided         */        if (null !== $response) {            $this->setResponse($response);        } elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) {            require_once 'Zend/Controller/Response/Http.php';            $response = new Zend_Controller_Response_Http();            $this->setResponse($response);        }        /**         * Register request and response objects with plugin broker         */        $this->_plugins             ->setRequest($this->_request)             ->setResponse($this->_response);        /**         * Initialize router         */        $router = $this->getRouter();        $router->setParams($this->getParams());        /**         * Initialize dispatcher         */        $dispatcher = $this->getDispatcher();        $dispatcher->setParams($this->getParams())                   ->setResponse($this->_response);        // Begin dispatch        try {            /**             * Route request to controller/action, if a router is provided             */            /**            * Notify plugins of router startup            */            $this->_plugins->routeStartup($this->_request);            try {                $router->route($this->_request);            }  catch (Exception $e) {                if ($this->throwExceptions()) {                    throw $e;                }                $this->_response->setException($e);            }            /**            * Notify plugins of router completion            */            $this->_plugins->routeShutdown($this->_request);            /**             * Notify plugins of dispatch loop startup             */            $this->_plugins->dispatchLoopStartup($this->_request);            /**             *  Attempt to dispatch the controller/action. If the $this->_request             *  indicates that it needs to be dispatched, move to the next             *  action in the request.             */            do {                $this->_request->setDispatched(true);                /**                 * Notify plugins of dispatch startup                 */                $this->_plugins->preDispatch($this->_request);                /**                 * Skip requested action if preDispatch() has reset it                 */                if (!$this->_request->isDispatched()) {                    continue;                }                /**                 * Dispatch request                 */                try {                    $dispatcher->dispatch($this->_request, $this->_response);                } catch (Exception $e) {                    if ($this->throwExceptions()) {                        throw $e;                    }                    $this->_response->setException($e);                }                /**                 * Notify plugins of dispatch completion                 */                $this->_plugins->postDispatch($this->_request);            } while (!$this->_request->isDispatched());        } catch (Exception $e) {            if ($this->throwExceptions()) {                throw $e;            }            $this->_response->setException($e);        }        /**         * Notify plugins of dispatch loop completion         */        try {            $this->_plugins->dispatchLoopShutdown();        } catch (Exception $e) {            if ($this->throwExceptions()) {                throw $e;            }            $this->_response->setException($e);        }        if ($this->returnResponse()) {            return $this->_response;        }        $this->_response->sendResponse();    }}

以上对Zend_Controller_Front和Zend_Controller_Dispatcher做了简单的标记,通过分析代码不难看出,基本的运行机制。

分发发生在前端控制器中的一个循环(loop)中。分发之前,前端控制器通过路由请求,找到用户指定的模块、控制器、动作和可选参数。然后进入分发循环,分发请求。

分发器需要大量数据完成任务――它需要知道如何格式化控制器和动作的名称,到哪儿找到控制器类文件,模块名是否有效,以及基于其它可用信息判定请求是否能分发的API。

每次迭代(iteration)过程开始时,在请求对象中设置一个标志指示该动作已分发。如果在动作或者前/后分发(pre/postDispatch)插件重置了该标志,分发循环将继续下去并试图分发新的请求。通过改变请求中的控制器或者动作并重置已分发标志,开发人员可以定制执行一个请求链。


控制这种分发过程的动作控制器方法是_forward();在任意的pre/postDispatch()或者动作中调用该方法,并传入动作、控制器、模块、以及可选的附加参数,就可以进入新的动作。

自定义分发器


Zend_Controller_Dispatcher_Interface定义了下列所有分发器需要实现的方法。
不过大多数情况下,只需要简单地扩展抽象类Zend_Controller_Dispatcher_Abstract,其中已经定义好了上面的大部分方法。或者扩展Zend_Controller_Dispatcher_Standard类,基于标准分发器来修改功能。
需要子类化分发器的可能原因包括:期望在动作控制器中使用不同的类和方法命名模式,或者期望使用不同的分发方式,比如分发到控制器目录下的动作文件,而不是控制器类的动作方法。



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

最新技术推荐