当前位置:首页 > CMS教程 > 其它CMS > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-13 15:39:58 浏览: 评论:0 

这篇文章主要介绍了Zend Framework教程之分发器Zend_Controller_Dispatcher用法,结合实例形式详细分析了分发器Zend_Controller_Dispatcher的结构,功能,使用技巧与相关注意事项,需要的朋友可以参考下。

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

分发器的具体实现

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

  1. ├── Dispatcher 
  2. │   ├── Abstract.php 
  3. │   ├── Exception.php 
  4. │   ├── Interface.php 
  5. │   └── Standard.php 

Zend_Controller_Dispatcher_Interface

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

  1. interface Zend_Controller_Dispatcher_Interface 
  2. { 
  3.   public function formatControllerName($unformatted); 
  4.   public function formatModuleName($unformatted); 
  5.   public function formatActionName($unformatted); 
  6.   public function isDispatchable(Zend_Controller_Request_Abstract $request); 
  7.   public function setParam($name, $value); 
  8.   public function setParams(array $params); 
  9.   public function getParam($name); 
  10.   public function getParams(); 
  11.   public function clearParams($name = null); 
  12.   public function setResponse(Zend_Controller_Response_Abstract $response = null); 
  13.   public function getResponse(); 
  14.   public function addControllerDirectory($path, $args = null); 
  15.   public function setControllerDirectory($path); 
  16.   public function getControllerDirectory(); 
  17.   public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response); 
  18.   public function isValidModule($module); 
  19.   public function getDefaultModule(); 
  20.   public function getDefaultControllerName(); 
  21.   public function getDefaultAction(); 
  22. } 

Zend_Controller_Dispatcher_Abstract

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

  1. <?php 
  2. /** Zend_Controller_Dispatcher_Interface */ 
  3. require_once 'Zend/Controller/Dispatcher/Interface.php'; 
  4. abstract class Zend_Controller_Dispatcher_Abstract implements Zend_Controller_Dispatcher_Interface 
  5. { 
  6.   protected $_defaultAction = 'index'; 
  7.   protected $_defaultController = 'index'; 
  8.   protected $_defaultModule = 'default'; 
  9.   protected $_frontController; 
  10.   protected $_invokeParams = array(); 
  11.   protected $_pathDelimiter = '_'; 
  12.   protected $_response = null; 
  13.   protected $_wordDelimiter = array('-', '.'); 
  14.   public function __construct(array $params = array()) 
  15.   { 
  16.     $this->setParams($params); 
  17.   } 
  18.   public function formatControllerName($unformatted) 
  19.   { 
  20.     return ucfirst($this->_formatName($unformatted)) . 'Controller'; 
  21.   } 
  22.   public function formatActionName($unformatted) 
  23.   { 
  24.     $formatted = $this->_formatName($unformatted, true); 
  25.     return strtolower(substr($formatted, 0, 1)) . substr($formatted, 1) . 'Action'; 
  26.   } 
  27.   public function _verifyDelimiter($spec) 
  28.   { 
  29.     if (is_string($spec)) { 
  30.       return (array) $spec; 
  31.     } elseif (is_array($spec)) { 
  32.       $allStrings = true; 
  33.       foreach ($spec as $delim) { 
  34.         if (!is_string($delim)) { 
  35.           $allStrings = false; 
  36.           break; 
  37.         } 
  38.       } 
  39.       if (!$allStrings) { 
  40.         require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  41.         throw new Zend_Controller_Dispatcher_Exception('Word delimiter array must contain only strings'); 
  42.       } 
  43.       return $spec; 
  44.     } 
  45.     require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  46.     throw new Zend_Controller_Dispatcher_Exception('Invalid word delimiter'); 
  47.   } 
  48.   public function getWordDelimiter() 
  49.   { 
  50.     return $this->_wordDelimiter; 
  51.   } 
  52.   public function setWordDelimiter($spec) 
  53.   { 
  54.     $spec = $this->_verifyDelimiter($spec); 
  55.     $this->_wordDelimiter = $spec; 
  56.     return $this; 
  57.   } 
  58.   public function getPathDelimiter() 
  59.   { 
  60.     return $this->_pathDelimiter; 
  61.   } 
  62.   public function setPathDelimiter($spec) 
  63.   { 
  64.     if (!is_string($spec)) { 
  65.       require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  66.       throw new Zend_Controller_Dispatcher_Exception('Invalid path delimiter'); 
  67.     } 
  68.     $this->_pathDelimiter = $spec; 
  69.     return $this; 
  70.   } 
  71.   protected function _formatName($unformatted, $isAction = false) 
  72.   { 
  73.     // preserve directories 
  74.     if (!$isAction) { 
  75.       $segments = explode($this->getPathDelimiter(), $unformatted); 
  76.     } else { 
  77.       $segments = (array) $unformatted; 
  78.     } 
  79.     foreach ($segments as $key => $segment) { 
  80.       $segment    = str_replace($this->getWordDelimiter(), ' ', strtolower($segment)); 
  81.       $segment    = preg_replace('/[^a-z0-9 ]/', '', $segment); 
  82.       $segments[$key] = str_replace(' ', '', ucwords($segment)); 
  83.     } 
  84.     return implode('_', $segments); 
  85.   } 
  86.   public function getFrontController() 
  87.   { 
  88.     if (null === $this->_frontController) { 
  89.       require_once 'Zend/Controller/Front.php'; 
  90.       $this->_frontController = Zend_Controller_Front::getInstance(); 
  91.     } 
  92.     return $this->_frontController; 
  93.   } 
  94.   public function setFrontController(Zend_Controller_Front $controller) 
  95.   { 
  96.     $this->_frontController = $controller; 
  97.     return $this; 
  98.   } 
  99.   public function setParam($name, $value) 
  100.   { 
  101.     $name = (string) $name; 
  102.     $this->_invokeParams[$name] = $value; 
  103.     return $this; 
  104.   } 
  105.   public function setParams(array $params) 
  106.   { 
  107.     $this->_invokeParams = array_merge($this->_invokeParams, $params); 
  108.     return $this; 
  109.   } 
  110.   public function getParam($name) 
  111.   { 
  112.     if(isset($this->_invokeParams[$name])) { 
  113.       return $this->_invokeParams[$name]; 
  114.     } 
  115.     return null; 
  116.   } 
  117.   public function getParams() 
  118.   { 
  119.     return $this->_invokeParams; 
  120.   } 
  121.   public function clearParams($name = null) 
  122.   { 
  123.     if (null === $name) { 
  124.       $this->_invokeParams = array(); 
  125.     } elseif (is_string($name) && isset($this->_invokeParams[$name])) { 
  126.       unset($this->_invokeParams[$name]); 
  127.     } elseif (is_array($name)) { 
  128.       foreach ($name as $key) { 
  129.         if (is_string($key) && isset($this->_invokeParams[$key])) { 
  130.           unset($this->_invokeParams[$key]); 
  131.         } 
  132.       } 
  133.     } 
  134.     return $this; 
  135.   } 
  136.   public function setResponse(Zend_Controller_Response_Abstract $response = null) 
  137.   { 
  138.     $this->_response = $response; 
  139.     return $this; 
  140.   } 
  141.   public function getResponse() 
  142.   { 
  143.     return $this->_response; 
  144.   } 
  145.   public function setDefaultControllerName($controller) 
  146.   { 
  147.     $this->_defaultController = (string) $controller; 
  148.     return $this; 
  149.   } 
  150.   public function getDefaultControllerName() 
  151.   { 
  152.     return $this->_defaultController; 
  153.   } 
  154.   public function setDefaultAction($action) 
  155.   { 
  156.     $this->_defaultAction = (string) $action; 
  157.     return $this; 
  158.   } 
  159.   public function getDefaultAction() 
  160.   { 
  161.     return $this->_defaultAction; 
  162.   } 
  163.   public function setDefaultModule($module) 
  164.   { 
  165.     $this->_defaultModule = (string) $module; 
  166.     return $this; 
  167.   } 
  168.   public function getDefaultModule() 
  169.   { 
  170.     return $this->_defaultModule; 
  171.   } 
  172. } 

Zend_Controller_Dispatcher_Standard

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

  1. <?php 
  2. /** Zend_Loader */ 
  3. require_once 'Zend/Loader.php'; 
  4. /** Zend_Controller_Dispatcher_Abstract */ 
  5. require_once 'Zend/Controller/Dispatcher/Abstract.php'; 
  6. class Zend_Controller_Dispatcher_Standard extends Zend_Controller_Dispatcher_Abstract 
  7. { 
  8.   protected $_curDirectory; 
  9.   protected $_curModule; 
  10.   protected $_controllerDirectory = array(); 
  11.   public function __construct(array $params = array()) 
  12.   { 
  13.     parent::__construct($params); 
  14.     $this->_curModule = $this->getDefaultModule(); 
  15.   } 
  16.   public function addControllerDirectory($path, $module = null) 
  17.   { 
  18.     if (null === $module) { 
  19.       $module = $this->_defaultModule; 
  20.     } 
  21.     $module = (string) $module; 
  22.     $path  = rtrim((string) $path, '/\\'); 
  23.     $this->_controllerDirectory[$module] = $path; 
  24.     return $this; 
  25.   } 
  26.   public function setControllerDirectory($directory, $module = null) 
  27.   { 
  28.     $this->_controllerDirectory = array(); 
  29.     if (is_string($directory)) { 
  30.       $this->addControllerDirectory($directory, $module); 
  31.     } elseif (is_array($directory)) { 
  32.       foreach ((array) $directory as $module => $path) { 
  33.         $this->addControllerDirectory($path, $module); 
  34.       } 
  35.     } else { 
  36.       require_once 'Zend/Controller/Exception.php'; 
  37.       throw new Zend_Controller_Exception('Controller directory spec must be either a string or an array'); 
  38.     } 
  39.     return $this; 
  40.   } 
  41.   public function getControllerDirectory($module = null) 
  42.   { 
  43.     if (null === $module) { 
  44.       return $this->_controllerDirectory; 
  45.     } 
  46.     $module = (string) $module; 
  47.     if (array_key_exists($module, $this->_controllerDirectory)) { 
  48.       return $this->_controllerDirectory[$module]; 
  49.     } 
  50.     return null; 
  51.   } 
  52.   public function removeControllerDirectory($module) 
  53.   { 
  54.     $module = (string) $module; 
  55.     if (array_key_exists($module, $this->_controllerDirectory)) { 
  56.       unset($this->_controllerDirectory[$module]); 
  57.       return true; 
  58.     } 
  59.     return false; 
  60.   } 
  61.   public function formatModuleName($unformatted) 
  62.   { 
  63.     if (($this->_defaultModule == $unformatted) && !$this->getParam('prefixDefaultModule')) { 
  64.       return $unformatted; 
  65.     } 
  66.     return ucfirst($this->_formatName($unformatted)); 
  67.   } 
  68.   public function formatClassName($moduleName, $className) 
  69.   { 
  70.     return $this->formatModuleName($moduleName) . '_' . $className; 
  71.   } 
  72.   public function classToFilename($class) 
  73.   { 
  74.     return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; 
  75.   } 
  76.   public function isDispatchable(Zend_Controller_Request_Abstract $request) 
  77.   { 
  78.     $className = $this->getControllerClass($request); 
  79.     if (!$className) { 
  80.       return false; 
  81.     } 
  82.     $finalClass = $className; 
  83.     if (($this->_defaultModule != $this->_curModule) 
  84.       || $this->getParam('prefixDefaultModule')) 
  85.     { 
  86.       $finalClass = $this->formatClassName($this->_curModule, $className); 
  87.     } 
  88.     if (class_exists($finalClass, false)) { 
  89.       return true; 
  90.     } 
  91.     $fileSpec  = $this->classToFilename($className); 
  92.     $dispatchDir = $this->getDispatchDirectory(); 
  93.     $test    = $dispatchDir . DIRECTORY_SEPARATOR . $fileSpec; 
  94.     return Zend_Loader::isReadable($test); 
  95.   } 
  96.   public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response) 
  97.   { 
  98.     $this->setResponse($response); 
  99.     /** 
  100.      * Get controller class 
  101.      */ 
  102.     if (!$this->isDispatchable($request)) { 
  103.       $controller = $request->getControllerName(); 
  104.       if (!$this->getParam('useDefaultControllerAlways') && !emptyempty($controller)) { 
  105.         require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  106.         throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')'); 
  107.       } 
  108.       $className = $this->getDefaultControllerClass($request); 
  109.     } else { 
  110.       $className = $this->getControllerClass($request); 
  111.       if (!$className) { 
  112.         $className = $this->getDefaultControllerClass($request); 
  113.       } 
  114.     } 
  115.     /** 
  116.      * Load the controller class file 
  117.      */ 
  118.     $className = $this->loadClass($className); 
  119.     /** 
  120.      * Instantiate controller with request, response, and invocation 
  121.      * arguments; throw exception if it's not an action controller 
  122.      */ 
  123.     $controller = new $className($request, $this->getResponse(), $this->getParams()); 
  124.     if (!($controller instanceof Zend_Controller_Action_Interface) && 
  125.       !($controller instanceof Zend_Controller_Action)) { 
  126.       require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  127.       throw new Zend_Controller_Dispatcher_Exception( 
  128.         'Controller "' . $className . '" is not an instance of Zend_Controller_Action_Interface' 
  129.       ); 
  130.     } 
  131.     /** 
  132.      * Retrieve the action name 
  133.      */ 
  134.     $action = $this->getActionMethod($request); 
  135.     /** 
  136.      * Dispatch the method call 
  137.      */ 
  138.     $request->setDispatched(true); 
  139.     // by default, buffer output 
  140.     $disableOb = $this->getParam('disableOutputBuffering'); 
  141.     $obLevel  = ob_get_level(); 
  142.     if (emptyempty($disableOb)) { 
  143.       ob_start(); 
  144.     } 
  145.     try { 
  146.       $controller->dispatch($action); 
  147.     } catch (Exception $e) { 
  148.       // Clean output buffer on error 
  149.       $curObLevel = ob_get_level(); 
  150.       if ($curObLevel > $obLevel) { 
  151.         do { 
  152.           ob_get_clean(); 
  153.           $curObLevel = ob_get_level(); 
  154.         } while ($curObLevel > $obLevel); 
  155.       } 
  156.       throw $e; 
  157.     } 
  158.     if (emptyempty($disableOb)) { 
  159.       $content = ob_get_clean(); 
  160.       $response->appendBody($content); 
  161.     } 
  162.     // Destroy the page controller instance and reflection objects 
  163.     $controller = null; 
  164.   } 
  165.   public function loadClass($className) 
  166.   { 
  167.     $finalClass = $className; 
  168.     if (($this->_defaultModule != $this->_curModule) 
  169.       || $this->getParam('prefixDefaultModule')) 
  170.     { 
  171.       $finalClass = $this->formatClassName($this->_curModule, $className); 
  172.     } 
  173.     if (class_exists($finalClass, false)) { 
  174.       return $finalClass; 
  175.     } 
  176.     $dispatchDir = $this->getDispatchDirectory(); 
  177.     $loadFile  = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className); 
  178.     if (Zend_Loader::isReadable($loadFile)) { 
  179.       include_once $loadFile; 
  180.     } else { 
  181.       require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  182.       throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $loadFile . "'"); 
  183.     } 
  184.     if (!class_exists($finalClass, false)) { 
  185.       require_once 'Zend/Controller/Dispatcher/Exception.php'; 
  186.       throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $finalClass . '")'); 
  187.     } 
  188.     return $finalClass; 
  189.   } 
  190.   public function getControllerClass(Zend_Controller_Request_Abstract $request) 
  191.   { 
  192.     $controllerName = $request->getControllerName(); 
  193.     if (emptyempty($controllerName)) { 
  194.       if (!$this->getParam('useDefaultControllerAlways')) { 
  195.         return false; 
  196.       } 
  197.       $controllerName = $this->getDefaultControllerName(); 
  198.       $request->setControllerName($controllerName); 
  199.     } 
  200.     $className = $this->formatControllerName($controllerName); 
  201.     $controllerDirs   = $this->getControllerDirectory(); 
  202.     $module = $request->getModuleName(); 
  203.     if ($this->isValidModule($module)) { 
  204.       $this->_curModule  = $module; 
  205.       $this->_curDirectory = $controllerDirs[$module]; 
  206.     } elseif ($this->isValidModule($this->_defaultModule)) { 
  207.       $request->setModuleName($this->_defaultModule); 
  208.       $this->_curModule  = $this->_defaultModule; 
  209.       $this->_curDirectory = $controllerDirs[$this->_defaultModule]; 
  210.     } else { 
  211.       require_once 'Zend/Controller/Exception.php'; 
  212.       throw new Zend_Controller_Exception('No default module defined for this application'); 
  213.     } 
  214.     return $className; 
  215.   } 
  216.   public function isValidModule($module) 
  217.   { 
  218.     if (!is_string($module)) { 
  219.       return false; 
  220.     } 
  221.     $module    = strtolower($module); 
  222.     $controllerDir = $this->getControllerDirectory(); 
  223.     foreach (array_keys($controllerDir) as $moduleName) { 
  224.       if ($module == strtolower($moduleName)) { 
  225.         return true; 
  226.       } 
  227.     } 
  228.     return false; 
  229.   } 
  230.   public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request) 
  231.   { 
  232.     $controller = $this->getDefaultControllerName(); 
  233.     $default  = $this->formatControllerName($controller); 
  234.     $request->setControllerName($controller) 
  235.         ->setActionName(null); 
  236.     $module       = $request->getModuleName(); 
  237.     $controllerDirs   = $this->getControllerDirectory(); 
  238.     $this->_curModule  = $this->_defaultModule; 
  239.     $this->_curDirectory = $controllerDirs[$this->_defaultModule]; 
  240.     if ($this->isValidModule($module)) { 
  241.       $found = false; 
  242.       if (class_exists($default, false)) { 
  243.         $found = true; 
  244.       } else { 
  245.         $moduleDir = $controllerDirs[$module]; 
  246.         $fileSpec = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default); 
  247.         if (Zend_Loader::isReadable($fileSpec)) { 
  248.           $found = true; 
  249.           $this->_curDirectory = $moduleDir; 
  250.         } 
  251.       } 
  252.       if ($found) { 
  253.         $request->setModuleName($module); 
  254.         $this->_curModule  = $this->formatModuleName($module); 
  255.       } 
  256.     } else { 
  257.       $request->setModuleName($this->_defaultModule); 
  258.     } 
  259.     return $default; 
  260.   } 
  261.   public function getDispatchDirectory() 
  262.   { 
  263.     return $this->_curDirectory; 
  264.   } 
  265.   public function getActionMethod(Zend_Controller_Request_Abstract $request) 
  266.   { 
  267.     $action = $request->getActionName(); 
  268.     if (emptyempty($action)) { 
  269.       $action = $this->getDefaultAction(); 
  270.       $request->setActionName($action); 
  271.     } 
  272.     return $this->formatActionName($action); 
  273.   } 
  274. } 

前端控制器和分发器

  1. <?php 
  2. /** Zend_Loader */ 
  3. require_once 'Zend/Loader.php'; 
  4. /** Zend_Controller_Action_HelperBroker */ 
  5. require_once 'Zend/Controller/Action/HelperBroker.php'; 
  6. /** Zend_Controller_Plugin_Broker */ 
  7. require_once 'Zend/Controller/Plugin/Broker.php'; 
  8. class Zend_Controller_Front 
  9. { 
  10.   protected $_baseUrl = null; 
  11.   protected $_controllerDir = null; 
  12.   protected $_dispatcher = null; 
  13.   protected static $_instance = null; 
  14.   protected $_invokeParams = array(); 
  15.   protected $_moduleControllerDirectoryName = 'controllers'; 
  16.   protected $_plugins = null; 
  17.   protected $_request = null; 
  18.   protected $_response = null; 
  19.   protected $_returnResponse = false; 
  20.   protected $_router = null; 
  21.   protected $_throwExceptions = false; 
  22.   protected function __construct() 
  23.   { 
  24.     $this->_plugins = new Zend_Controller_Plugin_Broker(); 
  25.   } 
  26.   private function __clone() 
  27.   { 
  28.   } 
  29.   public static function getInstance() 
  30.   { 
  31.     if (null === self::$_instance) { 
  32.       self::$_instance = new self(); 
  33.     } 
  34.     return self::$_instance; 
  35.   } 
  36.   public function resetInstance() 
  37.   { 
  38.     $reflection = new ReflectionObject($this); 
  39.     foreach ($reflection->getProperties() as $property) { 
  40.       $name = $property->getName(); 
  41.       switch ($name) { 
  42.         case '_instance': 
  43.           break; 
  44.         case '_controllerDir': 
  45.         case '_invokeParams': 
  46.           $this->{$name} = array(); 
  47.           break; 
  48.         case '_plugins': 
  49.           $this->{$name} = new Zend_Controller_Plugin_Broker(); 
  50.           break; 
  51.         case '_throwExceptions': 
  52.         case '_returnResponse': 
  53.           $this->{$name} = false; 
  54.           break; 
  55.         case '_moduleControllerDirectoryName': 
  56.           $this->{$name} = 'controllers'; 
  57.           break; 
  58.         default: 
  59.           $this->{$name} = null; 
  60.           break; 
  61.       } 
  62.     } 
  63.     Zend_Controller_Action_HelperBroker::resetHelpers(); 
  64.   } 
  65.   public static function run($controllerDirectory) 
  66.   { 
  67.     self::getInstance() 
  68.       ->setControllerDirectory($controllerDirectory) 
  69.       ->dispatch(); 
  70.   } 
  71.   public function addControllerDirectory($directory, $module = null) 
  72.   { 
  73.     $this->getDispatcher()->addControllerDirectory($directory, $module); 
  74.     return $this; 
  75.   } 
  76.   public function setControllerDirectory($directory, $module = null) 
  77.   { 
  78.     $this->getDispatcher()->setControllerDirectory($directory, $module); 
  79.     return $this; 
  80.   } 
  81.   public function getControllerDirectory($name = null) 
  82.   { 
  83.     return $this->getDispatcher()->getControllerDirectory($name); 
  84.   } 
  85.   public function removeControllerDirectory($module) 
  86.   { 
  87.     return $this->getDispatcher()->removeControllerDirectory($module); 
  88.   } 
  89.   public function addModuleDirectory($path) 
  90.   { 
  91.     try{ 
  92.       $dir = new DirectoryIterator($path); 
  93.     } catch(Exception $e) { 
  94.       require_once 'Zend/Controller/Exception.php'; 
  95.       throw new Zend_Controller_Exception("Directory $path not readable", 0, $e); 
  96.     } 
  97.     foreach ($dir as $file) { 
  98.       if ($file->isDot() || !$file->isDir()) { 
  99.         continue; 
  100.       } 
  101.       $module  = $file->getFilename(); 
  102.       // Don't use SCCS directories as modules 
  103.       if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) { 
  104.         continue; 
  105.       } 
  106.       $moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName(); 
  107.       $this->addControllerDirectory($moduleDir, $module); 
  108.     } 
  109.     return $this; 
  110.   } 
  111.   public function getModuleDirectory($module = null) 
  112.   { 
  113.     if (null === $module) { 
  114.       $request = $this->getRequest(); 
  115.       if (null !== $request) { 
  116.         $module = $this->getRequest()->getModuleName(); 
  117.       } 
  118.       if (emptyempty($module)) { 
  119.         $module = $this->getDispatcher()->getDefaultModule(); 
  120.       } 
  121.     } 
  122.     $controllerDir = $this->getControllerDirectory($module); 
  123.     if ((null === $controllerDir) || !is_string($controllerDir)) { 
  124.       return null; 
  125.     } 
  126.     return dirname($controllerDir); 
  127.   } 
  128.   public function setModuleControllerDirectoryName($name = 'controllers') 
  129.   { 
  130.     $this->_moduleControllerDirectoryName = (string) $name; 
  131.     return $this; 
  132.   } 
  133.   public function getModuleControllerDirectoryName() 
  134.   { 
  135.     return $this->_moduleControllerDirectoryName; 
  136.   } 
  137.   public function setDefaultControllerName($controller) 
  138.   { 
  139.     $dispatcher = $this->getDispatcher(); 
  140.     $dispatcher->setDefaultControllerName($controller); 
  141.     return $this; 
  142.   } 
  143.   public function getDefaultControllerName() 
  144.   { 
  145.     return $this->getDispatcher()->getDefaultControllerName(); 
  146.   } 
  147.   public function setDefaultAction($action) 
  148.   { 
  149.     $dispatcher = $this->getDispatcher(); 
  150.     $dispatcher->setDefaultAction($action); 
  151.     return $this; 
  152.   } 
  153.   public function getDefaultAction() 
  154.   { 
  155.     return $this->getDispatcher()->getDefaultAction(); 
  156.   } 
  157.   public function setDefaultModule($module) 
  158.   { 
  159.     $dispatcher = $this->getDispatcher(); 
  160.     $dispatcher->setDefaultModule($module); 
  161.     return $this; 
  162.   } 
  163.   public function getDefaultModule() 
  164.   { 
  165.     return $this->getDispatcher()->getDefaultModule(); 
  166.   } 
  167.   public function setRequest($request) 
  168.   { 
  169.     ........................... 
  170.     return $this; 
  171.   } 
  172.   public function getRequest() 
  173.   { 
  174.     return $this->_request; 
  175.   } 
  176.   public function setRouter($router) 
  177.   { 
  178.     .................... 
  179.     return $this; 
  180.   } 
  181.   public function getRouter() 
  182.   { 
  183.     .................. 
  184.     return $this->_router; 
  185.   } 
  186.   public function setBaseUrl($base = null) 
  187.   { 
  188.     .............. 
  189.     return $this; 
  190.   } 
  191.   public function getBaseUrl() 
  192.   { 
  193.     return $this->_baseUrl; 
  194.   } 
  195.   /** 
  196.    * Set the dispatcher object. The dispatcher is responsible for 
  197.    * taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and 
  198.    * call the action method of the controller. 
  199.    * 
  200.    * @param Zend_Controller_Dispatcher_Interface $dispatcher 
  201.    * @return Zend_Controller_Front 
  202.    */ 
  203.   public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher) 
  204.   { 
  205.     $this->_dispatcher = $dispatcher; 
  206.     return $this; 
  207.   } 
  208.   /** 
  209.    * Return the dispatcher object. 
  210.    * 
  211.    * @return Zend_Controller_Dispatcher_Interface 
  212.    */ 
  213.   public function getDispatcher() 
  214.   { 
  215.     /** 
  216.      * Instantiate the default dispatcher if one was not set. 
  217.      */ 
  218.     if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) { 
  219.       require_once 'Zend/Controller/Dispatcher/Standard.php'; 
  220.       $this->_dispatcher = new Zend_Controller_Dispatcher_Standard(); 
  221.     } 
  222.     return $this->_dispatcher; 
  223.   } 
  224.   public function setResponse($response) 
  225.   {.................. 
  226.     return $this; 
  227.   } 
  228.   public function getResponse() 
  229.   { 
  230.     return $this->_response; 
  231.   } 
  232.   public function setParam($name, $value) 
  233.   { 
  234.     $name = (string) $name; 
  235.     $this->_invokeParams[$name] = $value; 
  236.     return $this; 
  237.   } 
  238.   public function setParams(array $params) 
  239.   { 
  240.     $this->_invokeParams = array_merge($this->_invokeParams, $params); 
  241.     return $this; 
  242.   } 
  243.   public function getParam($name) 
  244.   { 
  245.     if(isset($this->_invokeParams[$name])) { 
  246.       return $this->_invokeParams[$name]; 
  247.     } 
  248.     return null; 
  249.   } 
  250.   public function getParams() 
  251.   { 
  252.     return $this->_invokeParams; 
  253.   } 
  254.   public function clearParams($name = null) 
  255.   { 
  256.     if (null === $name) { 
  257.       $this->_invokeParams = array(); 
  258.     } elseif (is_string($name) && isset($this->_invokeParams[$name])) { 
  259.       unset($this->_invokeParams[$name]); 
  260.     } elseif (is_array($name)) { 
  261.       foreach ($name as $key) { 
  262.         if (is_string($key) && isset($this->_invokeParams[$key])) { 
  263.           unset($this->_invokeParams[$key]); 
  264.         } 
  265.       } 
  266.     } 
  267.     return $this; 
  268.   } 
  269.   public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null) 
  270.   { 
  271.     $this->_plugins->registerPlugin($plugin, $stackIndex); 
  272.     return $this; 
  273.   } 
  274.   public function unregisterPlugin($plugin) 
  275.   { 
  276.     $this->_plugins->unregisterPlugin($plugin); 
  277.     return $this; 
  278.   } 
  279.   public function hasPlugin($class) 
  280.   { 
  281.     return $this->_plugins->hasPlugin($class); 
  282.   } 
  283.   public function getPlugin($class) 
  284.   { 
  285.     return $this->_plugins->getPlugin($class); 
  286.   } 
  287.   public function getPlugins() 
  288.   { 
  289.     return $this->_plugins->getPlugins(); 
  290.   } 
  291.   public function throwExceptions($flag = null) 
  292.   { 
  293.     ..................... 
  294.     return $this->_throwExceptions; 
  295.   } 
  296.   public function returnResponse($flag = null) 
  297.   { 
  298.     ................ 
  299.     return $this->_returnResponse; 
  300.   } 
  301.   /** 
  302.    * Dispatch an HTTP request to a controller/action. 
  303.    * 
  304.    * @param Zend_Controller_Request_Abstract|null $request 
  305.    * @param Zend_Controller_Response_Abstract|null $response 
  306.    * @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true 
  307.    */ 
  308.   public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null) 
  309.   { 
  310.     if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) { 
  311.       // Register with stack index of 100 
  312.       require_once 'Zend/Controller/Plugin/ErrorHandler.php'; 
  313.       $this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100); 
  314.     } 
  315.     if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) { 
  316.       require_once 'Zend/Controller/Action/Helper/ViewRenderer.php'; 
  317.       Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer()); 
  318.     } 
  319.     /** 
  320.      * Instantiate default request object (HTTP version) if none provided 
  321.      */ 
  322.     if (null !== $request) { 
  323.       $this->setRequest($request); 
  324.     } elseif ((null === $request) && (null === ($request = $this->getRequest()))) { 
  325.       require_once 'Zend/Controller/Request/Http.php'; 
  326.       $request = new Zend_Controller_Request_Http(); 
  327.       $this->setRequest($request); 
  328.     } 
  329.     /** 
  330.      * Set base URL of request object, if available 
  331.      */ 
  332.     if (is_callable(array($this->_request, 'setBaseUrl'))) { 
  333.       if (null !== $this->_baseUrl) { 
  334.         $this->_request->setBaseUrl($this->_baseUrl); 
  335.       } 
  336.     } 
  337.     /** 
  338.      * Instantiate default response object (HTTP version) if none provided 
  339.      */ 
  340.     if (null !== $response) { 
  341.       $this->setResponse($response); 
  342.     } elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) { 
  343.       require_once 'Zend/Controller/Response/Http.php'; 
  344.       $response = new Zend_Controller_Response_Http(); 
  345.       $this->setResponse($response); 
  346.     } 
  347.     /** 
  348.      * Register request and response objects with plugin broker 
  349.      */ 
  350.     $this->_plugins 
  351.        ->setRequest($this->_request) 
  352.        ->setResponse($this->_response); 
  353.     /** 
  354.      * Initialize router 
  355.      */ 
  356.     $router = $this->getRouter(); 
  357.     $router->setParams($this->getParams()); 
  358.     /** 
  359.      * Initialize dispatcher 
  360.      */ 
  361.     $dispatcher = $this->getDispatcher(); 
  362.     $dispatcher->setParams($this->getParams()) 
  363.           ->setResponse($this->_response); 
  364.     // Begin dispatch 
  365.     try { 
  366.       /** 
  367.        * Route request to controller/action, if a router is provided 
  368.        */ 
  369.       /** 
  370.       * Notify plugins of router startup 
  371.       */ 
  372.       $this->_plugins->routeStartup($this->_request); 
  373.       try { 
  374.         $router->route($this->_request); 
  375.       } catch (Exception $e) { 
  376.         if ($this->throwExceptions()) { 
  377.           throw $e; 
  378.         } 
  379.         $this->_response->setException($e); 
  380.       } 
  381.       /** 
  382.       * Notify plugins of router completion 
  383.       */ 
  384.       $this->_plugins->routeShutdown($this->_request); 
  385.       /** 
  386.        * Notify plugins of dispatch loop startup 
  387.        */ 
  388.       $this->_plugins->dispatchLoopStartup($this->_request); 
  389.       /** 
  390.        * Attempt to dispatch the controller/action. If the $this->_request 
  391.        * indicates that it needs to be dispatched, move to the next 
  392.        * action in the request. 
  393.        */ 
  394.       do { 
  395.         $this->_request->setDispatched(true); 
  396.         /** 
  397.          * Notify plugins of dispatch startup 
  398.          */ 
  399.         $this->_plugins->preDispatch($this->_request); 
  400.         /** 
  401.          * Skip requested action if preDispatch() has reset it 
  402.          */ 
  403.         if (!$this->_request->isDispatched()) { 
  404.           continue; 
  405.         } 
  406.         /** 
  407.          * Dispatch request 
  408.          */ 
  409.         try { 
  410.           $dispatcher->dispatch($this->_request, $this->_response); 
  411.         } catch (Exception $e) { 
  412.           if ($this->throwExceptions()) { 
  413.             throw $e; 
  414.           } 
  415.           $this->_response->setException($e); 
  416.         } 
  417.         /** 
  418.          * Notify plugins of dispatch completion 
  419.          */ 
  420.         $this->_plugins->postDispatch($this->_request); 
  421.       } while (!$this->_request->isDispatched()); 
  422.     } catch (Exception $e) { 
  423.       if ($this->throwExceptions()) { 
  424.         throw $e; 
  425.       } 
  426.       $this->_response->setException($e); 
  427.     } 
  428.     /** 
  429.      * Notify plugins of dispatch loop completion 
  430.      */ 
  431.     try { 
  432.       $this->_plugins->dispatchLoopShutdown(); 
  433.     } catch (Exception $e) { 
  434.       if ($this->throwExceptions()) { 
  435.         throw $e; 
  436.       } 
  437.       $this->_response->setException($e); 
  438.     } 
  439.     if ($this->returnResponse()) { 
  440.       return $this->_response; 
  441.     } 
  442.     $this->_response->sendResponse(); 
  443.   } 
  444. } 

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

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

Tags: Framework Zend_Controller_Dispatcher

分享到: