Zend的MVC机制使用分析(一)
前端之家收集整理的这篇文章主要介绍了
Zend的MVC机制使用分析(一),
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_301_0@
<div class="codetitle">
<a style="CURSOR: pointer" data="57741" class="copybut" id="copybut57741" onclick="doCopy('code57741')"> 代码如下: <div class="codebody" id="code57741">
$front = Zend_Controller_Front::getInstance();
Zend_Layout::startMvc(array('layoutPath' => USVN_LAYOUTS_DIR)); $front->setRequest(new USVN_Controller_Request_Http());
$front->throwExceptions(true);
$front->setBaseUrl($config->url->base); $router = new Zend_Controller_Router_Rewrite();
$routes_config = new USVN_Config_Ini(USVN_ROUTES_CONFIG_FILE,USVN_CONFIG_SECTION);
$router->addConfig($routes_config,'routes');
$front->setRouter($router);
$front->setControllerDirectory(USVN_CONTROLLERS_DIR); Zend_Controller_Front::getInstance()->dispatch();
分析
首先看下Zend_Controller_Front::getInstance是
调用单例模式,实例化了它的内部
属性_plugins,实例化了一个Zend_Controller_Plugin
Broker类。
@H301_0@这个类是管理front的
插件的类。先看一个Front中的
方法public function registerPlugin(Zend_Controller_Plugin
Abstract $plugin,$stackIndex = null)
@H301_0@意思是如果你有一个自己的
插件要插入使用的话,
调用这个
函数能把你自己的
插件委托给Zend_Controller_Plugin
Broker使用。
@H301_0@如果你有愿望继续跟下去你会看到
注册插件做的一件最根本的事情就是把request和response放入到你的
插件中去(setRequest和setResponse)。
@H_
301_0@class Zend_Controller_Plugin_Broker extends Zend_Controller_Plugin
Abstract
@H301_0@这个实现了抽象类Zend_Controller_Plugin_Abstract。
Zend_Controller_Plugin_Abstract是所有
插件的抽象类,所有
用户自己定义的
插件或者Zend已有的
插件都要从这个类继承。这里就看到了,前端控制器Front就是使用broker作为
用户插件注册。
@H_
301_0@这个抽象类可以被实现的
函数有:
<IMG alt="" src="https://files.jb51.cc/file_images/article/201304/201305021026357.png">
@H_
301_0@routeStartup: 在路由发送请求前被
调用
@H_
301_0@routeShutdown:在路由完成请求后被
调用
@H_
301_0@dispatchLoopStartup:在进入分发循环(dispatch loop)前被
调用
@H_
301_0@Predispatch:在动作由分发器分发前被
调用
@H_
301_0@postdispatch:在动作由路由器分发后被
调用
@H_
301_0@dispatchLoopShutdown:在进入分发循环(dispatch loop)后被
调用
@H_
3010@
@H301_0@我们还看到了getRequest,getResponse两个
方法,我们可以通过他们分别从控制器中
获取request对象和response对象
@H_
3010@
@H301_0@好了,扯远了,回到最开始的
代码,Zend_Controller_Front::getInstance实际上来看做的事情就是
注册了一个broker
插件放到$front中。
@H_
3010@
@H301_0@下面一行
代码
@H_
301_0@Zend_Layout::startMvc(array('layoutPath' => USVN_LAYOUTS
DIR));
@H301_0@看到Zend/Layout.
PHP中,startMvc做了两件事:首先是
调用自己的构造
函数来实例化自己(切记带着initMvc参数为true),然后是设置参数。
@H_
301_0@Zend_Layout的构造
函数比较复杂,就跟到里面看看。首先也是设置传递进来的参数$options,我们这个例子中是传递进来Array ( [layoutPath] => /var/www/html/usvn/app/layouts )这个array作为options,构造
函数就是
调用$this->setOptions($options);
@H_
301_0@这个setOptions做的事是根据array的每个key,
调用$this->set$key($val);也就是说,以上面的例子来说,setOptions
调用了setLayoutPath("/var/www/html/usvn/app/layouts")
@H_
301_0@顺藤摸瓜,setLayoutPath的
功能是设置自己类的this->_layout为"/var/www/html/usvn/app/layouts", 然后设置_enable为true;这两个
属性记住,以后会有使用的。
@H_
3010@
@H301_0@回退到Zend_Layout的构造
函数,初始化options之后是
调用了
initVarContainer();
@H301_0@这个
函数做了这么个事情:
@H_
301_0@$this->_container = Zend_View_Helper_Placeholder
Registry::getRegistry()->getContainer(CLASS);
@H301_0@又出现了Zend_View_Helper_Placeholder_Registry(我翻译为:Zend视图助手
注册表)
@H_
3010@
@H301_0@getRegistry() 将Zend_View_Helper_Placeholder_Registry作为key,Zend_View_Helper_Placeholder_Registry类的实例作为value
注册到之前见过的Zend_Registry中。这个类的构造
函数就什么事都没有。
@H_
3010@
@H301_0@getRegistry()返回了Zend_View_Helper_Placeholder_Registry实例,下面
调用getContainer(
CLASS)。 这里的
CLASS是什么,当前
调用的类,自然就是Zend_Layout了。这里是getContainer("Zend
Layout")
@H3010@
@H301_0@进入到getContainer里面,它
调用了createContainer("Zend_Layout")。createContainer("Zend_Layout")是在Registry中以Zend_Layout为key,Zend_View_Helper_Placeholder
Container类为value的array。
@H3010@
@H301_0@Zend_View_Helper_Placeholder_Container实现抽象类Zend_View_Helper_Placeholder_Container_Abstract,这个抽象类实际上也是一个ArrayObject,这个在之前的
文章有提到过了,是一个和泛型类一样的东东。
@H_
3010@
@H301_0@好了,这里不跟下去了,回头到Zend_Layout的构造
函数
@H_
301_0@_initVarContainer结束了,下面是
调用两个重要的
函数:
@H_
301_0@$this->
setMvcEnabled(true);
@H301_0@$this->
initMvc();
@H3010@Mvc大家一定很熟悉,我们来看看这里是怎么个MVC的
@H301_0@setMvcEnabled没什么特别,设置标志位this->
mvcEnabled
@H301_0@_initMvc做了两件事,_initPlugin和
initHelper。
@H3010@先看initPlugin:
@H301_0@
获取PluginClass,这里的pluginClass就是Zend_Layout_Controller_Plugin_Layout,可以看到,这里是作为一个
插件的形式放进来的。
@H_
301_0@接着又
获取了Zend_Controller_Front的实例,
调用:
@H_
3010@$front->registerPlugin(
@H3010@new $pluginClass($this),
@H3010@99
@H3010@);
@H3010@
@H301_0@记得前面对Zend_Controller_Front的分析不?里面有registerPlugin的
函数,是将
插件委托给front的broker来用。有人就会问后面的99是什么意思?是
插件的索引顺序,越后面的
插件越
后执行插件的动作。
@H_
3010@
@H301_0@下面再看
initHelper:
@H301_0@
获取helperClass,这里的helperClass就是Zend_Layout_Controller_Action_Helper
Layout
@H301_0@if (!Zend_Controller_Action
HelperBroker::hasHelper('layout')) {
@H3010@。。。
@H301_0@Zend_Controller_Action
HelperBroker::getStack()->offsetSet(-90,new $helperClass($this));
@H3010@}
@H301_0@如果Action
HelperBroker没有layout的helper的话
@H301_0@就执行下面的offsetSet命令。将-90和Zend_Layout_Controller_Action_Helper
Layout实例作为参数传入。
@H301_0@和plugin同样的关系,将Zend_Layout_Controller_Action_Helper_Layout实例作为value存入到this->_helpersByPriority和this->
helpersByNameRef去了
@H301_0@前面的-90是权重,也是要保证这个helper是最后
调用(看最后一行是krsort排序)
@H_
301_0@好了,Layout的构造
函数就这样分析结束了。