Zend Framework教程之分发器Zend_Controller_Dispatcher用法详解
本文实例讲述了zend framework教程之分发器zend_controller_dispatcher用法。分享给大家供大家参考,具体如下:
分发器的具体实现
zend framework的分发器zend_controller_dispatcher设计主要有,如下类和接口组成:
├── dispatcher
│ ├── abstract.php
│ ├── exception.php
│ ├── interface.php
│ └── standard.php
zend_controller_dispatcher_interface
定义了分发器提供的基本和标准功能。
interface zend_controller_dispatcher_interface { public function formatcontrollername($unformatted); public function formatmodulename($unformatted); public function formatactionname($unformatted); public function isdispatchable(zend_controller_request_abstract $request); public function setparam($name, $value); public function setparams(array $params); public function getparam($name); public function getparams(); public function clearparams($name = null); public function setresponse(zend_controller_response_abstract $response = null); public function getresponse(); public function addcontrollerdirectory($path, $args = null); public function setcontrollerdirectory($path); public function getcontrollerdirectory(); public function dispatch(zend_controller_request_abstract $request, zend_controller_response_abstract $response); public function isvalidmodule($module); public function getdefaultmodule(); public function getdefaultcontrollername(); public function getdefaultaction(); }
zend_controller_dispatcher_abstract
实现了zend_controller_dispatcher_interface接口,提供了分发器提供的基本和标准功能的抽象父类。
<?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程序设计有所帮助。
推荐阅读
-
Zend Framework教程之视图组件Zend_View用法详解
-
Zend Framework教程之Application用法实例详解_php实例
-
Zend Framework教程之资源(Resources)用法实例详解,zendframework_PHP教程
-
Zend Framework教程之Loader以及PluginLoader用法详解_php实例
-
Zend Framework教程之分发器Zend_Controller_Dispatcher用法详解_php实例
-
Zend Framework教程之Autoloading用法详解_php实例
-
Zend Framework教程之前端控制器Zend_Controller_Front用法详解_php实例
-
Zend Framework教程之Zend_Controller_Plugin插件用法详解,zendframework_PHP教程
-
Zend Framework教程之Autoloading用法详解,zendautoloading
-
Zend Framework动作助手(Zend_Controller_Action_Helper)用法详解,zendhelper_PHP教程