首页 > 开发 > PHP > 正文

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

2024-05-04 23:43:38
字体:
来源:转载
供稿:网友
这篇文章主要介绍了Zend Framework教程之分发器Zend_Controller_Dispatcher用法,结合实例形式详细分析了分发器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接口,提供了分发器提供的基本和标准功能的抽象父类。

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

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



注:相关教程知识阅读请移步到PHP教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表