Zend的MVC机制使用分析(一)

代码


代码如下:

$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类。

这个类是管理front的插件的类。先看一个Front中的方法public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)

意思是如果你有一个自己的插件要插入使用的话,调用这个函数能把你自己的插件委托给Zend_Controller_Plugin_Broker使用。

如果你有愿望继续跟下去你会看到注册插件做的一件最根本的事情就是把request和response放入到你的插件中去(setRequest和setResponse)。

class Zend_Controller_Plugin_Broker extends Zend_Controller_Plugin_Abstract

这个实现了抽象类Zend_Controller_Plugin_Abstract。
Zend_Controller_Plugin_Abstract是所有插件的抽象类,所有用户自己定义的插件或者Zend已有的插件都要从这个类继承。这里就看到了,前端控制器Front就是使用broker作为用户插件注册。

这个抽象类可以被实现的函数有:

routeStartup: 在路由发送请求前被调用

routeShutdown:在路由完成请求后被调用

dispatchLoopStartup:在进入分发循环(dispatch loop)前被调用

Predispatch:在动作由分发器分发前被调用

postdispatch:在动作由路由器分发后被调用

dispatchLoopShutdown:在进入分发循环(dispatch loop)后被调用

我们还看到了getRequest, getResponse两个方法,我们可以通过他们分别从控制器中获取request对象和response对象

好了,扯远了,回到最开始的代码,Zend_Controller_Front::getInstance实际上来看做的事情就是注册了一个broker插件放到$front中。

下面一行代码

Zend_Layout::startMvc(array('layoutPath' => USVN_LAYOUTS_DIR));

看到Zend/Layout.php中,startMvc做了两件事:首先是调用自己的构造函数来实例化自己(切记带着initMvc参数为true),然后是设置参数。

Zend_Layout的构造函数比较复杂,就跟到里面看看。首先也是设置传递进来的参数$options,我们这个例子中是传递进来Array ( [layoutPath] => /var/www/html/usvn/app/layouts )这个array作为options,构造函数就是调用$this->setOptions($options);

这个setOptions做的事是根据array的每个key,调用$this->set$key($val);也就是说,以上面的例子来说,setOptions调用了setLayoutPath("/var/www/html/usvn/app/layouts")

顺藤摸瓜,setLayoutPath的功能是设置自己类的this->_layout为"/var/www/html/usvn/app/layouts", 然后设置_enable为true;这两个属性记住,以后会有使用的。

回退到Zend_Layout的构造函数,初始化options之后是调用了_initVarContainer();

这个函数做了这么个事情:

$this->_container = Zend_View_Helper_Placeholder_Registry::getRegistry()->getContainer(__CLASS__);

又出现了Zend_View_Helper_Placeholder_Registry(我翻译为:Zend视图助手注册表)

getRegistry() 将Zend_View_Helper_Placeholder_Registry作为key,Zend_View_Helper_Placeholder_Registry类的实例作为value注册到之前见过的Zend_Registry中。这个类的构造函数就什么事都没有。

getRegistry()返回了Zend_View_Helper_Placeholder_Registry实例,下面调用getContainer(__CLASS__)。 这里的__CLASS__是什么,当前调用的类,自然就是Zend_Layout了。这里是getContainer("Zend_Layout")

进入到getContainer里面,它调用了createContainer("Zend_Layout")。createContainer("Zend_Layout")是在Registry中以Zend_Layout为key,Zend_View_Helper_Placeholder_Container类为value的array。

Zend_View_Helper_Placeholder_Container实现抽象类Zend_View_Helper_Placeholder_Container_Abstract,这个抽象类实际上也是一个ArrayObject,这个在之前的文章有提到过了,是一个和泛型类一样的东东。

好了,这里不跟下去了,回头到Zend_Layout的构造函数

_initVarContainer结束了,下面是调用两个重要的函数:

$this->_setMvcEnabled(true);

$this->_initMvc();

Mvc大家一定很熟悉,我们来看看这里是怎么个MVC的

setMvcEnabled没什么特别,设置标志位this->_mvcEnabled

_initMvc做了两件事,_initPlugin和_initHelper。

先看initPlugin:

获取PluginClass,这里的pluginClass就是Zend_Layout_Controller_Plugin_Layout,可以看到,这里是作为一个插件的形式放进来的。

接着又获取了Zend_Controller_Front的实例,调用:

$front->registerPlugin(

new $pluginClass($this),

99

);

记得前面对Zend_Controller_Front的分析不?里面有registerPlugin的函数,是将插件委托给front的broker来用。有人就会问后面的99是什么意思?是插件的索引顺序,越后面的插件越后执行插件的动作。

下面再看_initHelper:

获取helperClass,这里的helperClass就是Zend_Layout_Controller_Action_Helper_Layout

if (!Zend_Controller_Action_HelperBroker::hasHelper('layout')) {

。。。

Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-90, new $helperClass($this));

}

如果Action_HelperBroker没有layout的helper的话

就执行下面的offsetSet命令。将-90和Zend_Layout_Controller_Action_Helper_Layout实例作为参数传入。

和plugin同样的关系,将Zend_Layout_Controller_Action_Helper_Layout实例作为value存入到this->_helpersByPriority和this->_helpersByNameRef去了

前面的-90是权重,也是要保证这个helper是最后调用(看最后一行是krsort排序)

好了,Layout的构造函数就这样分析结束了。

(0)

相关推荐

  • Zend的MVC机制使用分析(一)

    代码 复制代码 代码如下: $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->

  • Zend的MVC机制使用分析(二)

    接着上面的一篇 把代码贴上来 复制代码 代码如下: $front = Zend_Controller_Front::getInstance(); Zend_Layout::startMvc(array('layoutPath' => USVN_LAYOUTS_DIR)); $front->setRequest(new Zend_Controller_Request_Http()); $front->throwExceptions(true); $front->setBaseUrl(

  • 基于Zend的Config机制的应用分析

    Zend的Config类在Zend_Config_Ini 代码$config = new Zend_Config_Ini("/var/www/html/usvn/config/config.ini", "general"); date_default_timezone_set($config->timezone); USVN_ConsoleUtils::setLocale($config->system->locale); === Config.i

  • Zend的Registry机制的使用说明

    项目过程中有很多全局变量, 需要全局存储,是否是使用全局变量来进行存储?那就弱爆了.Zend使用Registry机制(注册表)存储对象和值,是一个存储对象和值的容器. Zend_Registry这个类就是做这个目的 代码示例Zend_Registry::set('config', $config); Zend_Registry::get('config'); 代码分析这两个函数是最常用的两个函数.我们来看一下这个类 class Zend_Registry extends ArrayObject

  • PHP及Zend Engine的线程安全模型分析

    不知道怎么回事总是令人不舒服的,因此我通过阅读源码和查阅有限的资料简要了解一下相关机制,本文是我对研究内容的总结. 本文首先解释了线程安全的概念及PHP中线程安全的背景,然后详细研究了PHP的线程安全机制ZTS(Zend Thread Safety)及具体的实现TSRM,研究内容包括相关数据结构.实现细节及运行机制,最后研究了Zend对于单线程和多线程环境的选择性编译问题. 线程安全 线程安全问题,一言以蔽之就是多线程环境下如何安全存取公共资源.我们知道,每个线程只拥有一个私有栈,共享所属进程的

  • Java的RTTI和反射机制代码分析

    RTTI,即Run-Time Type Identification,运行时类型识别.运行时类型识别是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息.RTTI能在运行时就能够自动识别每个编译时已知的类型. 很多时候需要进行向上转型,比如Base类派生出Derived类,但是现有的方法只需要将Base对象作为参数,实际传入的则是其派生类的引用.那么RTTI就在此时起到了作用,比如通过RTTI能识别出Derive类是Base的派生类,这样就能够向上转型为Derived.类似的,

  • Android 图片的三级缓存机制实例分析

    Android 图片的三级缓存机制实例分析 当我们获取图片的时候,如果不加以协调好图片的缓存,就会造成大流量,费流量应用,用户体验不好,影响后期发展.为此,我特地分享Android图片的三级缓存机制之从网络中获取图片,来优化应用,具体分三步进行: (1)从缓存中获取图片 (2)从本地的缓存目录中获取图片,并且获取到之后,放到缓存中 (3)从网络去下载图片,下载完成之后,保存到本地和放到缓存中 很好的协调这三层图片缓存就可以大幅度提升应用的性能和用户体验. 快速实现三级缓存的工具类ImageCac

  • Python 内存管理机制全面分析

    内存管理: 概述 在Python中,内存管理涉及到一个包含所有Python对象和数据结构的私有堆(heap). 这个私有堆的管理由内部的Python内存管理器保证.Python内存管理器有不同的组件来处理各种动态存储管理方面的问题,如共享,分割,预分配或缓存. 在最底层,一个原始内存分配器通过与操作系统的内存管理器交互,确保私有堆有足够的空间来存储所有与Python相关的数据.在原始内存分配器的基础上,几个对象特定的分配器在同一个堆上运行,并根据每种对象类型的特点实现不同的内存管理策略.例如,整

  • elasticsearch的灵魂唯一master选举机制原理分析

    master作为cluster的灵魂必须要有,还必须要唯一,否则集群就出大问题了.因此master选举在cluster分析中尤为重要.对于这个问题我将分两篇来分析.第一篇也就是本篇,首先会简单说一说mater选举的一些算法,及elasticsearch的选举原理.第二篇也就是下一篇,会结合zenDiscovery代码为仔细分析elasticsearch的master选举的实现. 简单来说master的作用跟单个jvm中的同步关键字synchronized相同,集群中多节点协调工作必须要保证数据的

  • elasticsearch的zenDiscovery和master选举机制原理分析

    目录 前言 join的代码 findMaster方法 总结 前言 上一篇通过 ElectMasterService源码,分析了master选举的原理的大部分内容:master候选节点ID排序保证选举一致性及通过设置最小可见候选节点数目避免brain split.节点排序后选举只能保证局部一致性,如果发生节点接收到了错误的集群状态就会选举出错误的master,因此必须有其它措施来保证选举的一致性.这就是上一篇所提到的第二点:被选举的数量达到一定的数目同时自己也选举自己,这个节点才能成为master

随机推荐