• 技术文章 >php教程 >php手册

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

    2016-06-06 19:34:24原创447

    本文实例讲述了Zend Framework教程之分发器Zend_Controller_Dispatcher用法。分享给大家供大家参考,具体如下: 分发器的具体实现 Zend Framework的分发器Zend_Controller_Dispatcher设计主要有,如下类和接口组成: ├── Dispatcher │ ├── Abstract.p

    本文实例讲述了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类,基于标准分发器来修改功能。

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

    更多关于zend相关内容感兴趣的读者可查看本站专题:《Zend FrameWork框架入门教程》、《php优秀开发框架总结》、《Yii框架入门及常用技巧总结》、《ThinkPHP入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

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

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:php实现无限级分类查询(递归、非递归) 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 我的论坛源代码(五)• 使用PHP4.2.0及以后版本的注意事项• PHP之判断用户语言跳转网页• PHP 修改RAR文件注释及添加压缩文档讲解• php 树型结构操作类代码(1/4)
    1/1

    PHP中文网