php分发器,Zend Framework教程之分发器Zend_Controller_Dispatcher用法详解

本文实例讲述了Zend Framework教程之分发器Zend_Controller_Dispatcher用法。分享给大家供大家参考,具体如下:

分发器的具体实现

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接口,提供了分发器提供的基本和标准功能的抽象父类。

/** 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提供的基本的分发器,完成了分发功能。

/** 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);

}

}

前端控制器和分发器

/** 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类,基于标准分发器来修改功能。

需要子类化分发器的可能原因包括:期望在动作控制器中使用不同的类和方法命名模式,或者期望使用不同的分发方式,比如分发到控制器目录下的动作文件,而不是控制器类的动作方法。

希望本文所述对大家PHP程序设计有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值