本文实例讲述了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接口,提供了分发器提供的基本和标准功能的抽象父类。
<"htmlcode"><"' . $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); } }前端控制器和分发器
<"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程序设计有所帮助。
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。