ZendFramework 2框架之MVC
作者:sys(360电商技术组)
1.前言
Zend Framework 2是zend官方推出的php开源框架,基于php5.3。他全然採用面向对象的代码实现,并利用了php5.3的一些新特性,比方命名空间。闭包等。由于是官方的推荐的,今天我们就来学习学习Zend Framework 2,由于本人知识浅薄,也没有实际的用Zend Framework 2做项目开发的经验。有错误的地方还请大家指正,也希望在后面的开发中能用用该框架,此篇文章权当抛砖引玉。
2.体会
相对于我们如今用的QFrame,ZendFramework 2让我感觉还是相当复杂。可能QFrame我们仅仅用一天的时间。就能全然了解里面的详细实现。可是Zend Framework 2看了几天还是让我无所适从。
让我感觉QFrame非常实在,非常落地,学习使用相对easy,而Zend Framework 2就有点复杂了。Zend Framework 2的MVC主要採用了Service Locator和事件驱动的设计模式。他提倡不论什么类库,扩展等资源都统一被视为服务对象。由一个管理者进行管理,全部服务对象都须要注冊给管理者。
当应用程序须要某些资源的时候,都从管理者中获取资源。这样的方法的优点在于解除了服务调用者和服务提供者之间的耦合。
Zend Framework 2中用了非常多设计模式,这一点,是自己须要提高的。在我们实际业务开发中,用的模式比較少,希望在这方面有所加强。
另一个,我的体会是,Zend Framework 2在编码规范和凝视方面做的比較好。这让我想起来了一篇文章,说谷歌为什么严格运行代码规范,大家开能够看看:http://developer.51cto.com/art/201108/283275.htm。
这里说说Zend Framework 2的环境搭建以及Zend Framework 2的mvc的形式,主要是一些网上和自己的一些使用心得。
3.环境搭建
我是依照官方的教程搭建的。
1. 首先下载Zend Framework 2的框架。
从官方站点 http://framework.zendcom/downloads/latest就能够下载到最新的Zend Framework 2框架,我用的版本号是2.3.0。将下载的源代码放到文件夹 /home/q/php/ZendFramework 以下。然后改动php.ini加入一个include_path进去 Zend Framework 2_path ="/home/q/php/ZendFramework/library"
2. 搭建开发模板环境。
也能够从官方下载演示样例模板开发环境。
官方提供了三种方法安装。网址:http://framework.zend.com/downloads/skeleton-app,第一种是用包的形式,另外一种使用Git的形式。第三种是下载压缩包。我用的是最原始的方法,下载压缩包。下载完之后,你把它放到你喜欢的文件夹。
4.应用演示样例
好,如今来看一下我们下载的一个演示样例模板
大概的文件夹结构就是这样的,入口是public/index.php文件。发现这个结构是不是似曾相识呢。对,和我们如今使用的QFrame非常像。以下简介一下各个文件夹和文件的功能。
文件和文件夹结构
1. /public文件夹
public文件夹是放css。js。img等的一下资源文件。public/index.php是项目的入口文件,ngx配置的路径就是这个文件夹的路径。
public/index.php文件非常少
2./init_autoloader.php
顾名思义,此文件是自己主动载入类用的。
3./config
Config文件夹,是放配置用的。
这里,ZendFramework 2又细分了一下application.config.php 这个配置是应用程序级别的配置,是与整个项目有关的。比方须要载入哪些module的配置。
/config/autoload/文件夹下存放的是项目环境有关的配置信息。
4./vendor
vendor文件夹一般存放第三方开发的或是自己开发的通用的模块
5./module
module文件夹一般存放当前项目的模块,每一个Module就是一个全然独立的功能模块,能够拥有自己的配置文件、语言文件等等。
/module/Application就是详细的一个module。/module/Application/Module.php是此module的配置信息,每一个新加的module必须有这个文件。/module/Application/config/module.config.php这里是对路由,控制器等的一些配置。/module/Application/src/里面主要是详细的控制器的实现,/module/Application/view里面主要是tpl文件。
我们在新加一个module的时候,文件夹结构也须要是相似的一个形式。
5.技术点解析
上面说到Zend Framework 2採用了Server Locator 和事件驱动的模式,这里我们简介一下ServerLocator和事件驱动
1. Server Locator
Zend Framework 2中用来实现Server Locator的是 Zend/ServiceManager/这个组件。
在Zend Framework 2中,不论什么的类库,扩展等资源都统一被视为服务对象,并在ServiceManager组件中注冊。当应用程序须要某个功能,比如Zend\Log 时,推荐的做法是在ServiceManager中获取。而不是像传统方式那样,include类文件之后再new一个对象出来。这样的方式的优点在于解除了服务调用者与服务提供者之间的耦合。作为使用者,不须要知道Zend\Log位置是在哪里,是怎样产生的。仅仅须要知道用Zend\ServiceManager::get()这样的方式来取得它即可了。
在这里,Zend Framework 2提供了4中注冊对象的方法
- 初始化好的对象
调用setService方法,直接将创建好的对象注冊到管理器中
- 延迟创建对象
调用setInvokableClass方法。事实上就是先注冊一个类的名字。当须要使用该服务对象时,ServiceManager实例化一个对象给你。
- 工厂对象
调用setFactory方法。有很多服务对象的产生比較复杂,比方依据配置文件的内容来产生对象等。这时就须要有个专门的“工厂”来产生服务对象。工厂能够是匿名函数。也能够是实现了Zend\ServiceManager\FactoryInterface的类或对象。
- 抽象工厂对象
假设要取得一个名字不存在的服务对象时。ServiceManager会去寻找注冊的抽象工厂,抽象工厂实现了Zend\ServiceManager\AbstractFactoryInterface,假设有某个抽象工厂的canCreateServiceWithName方法返回true,则 ServiceManager返回该抽象工厂的createServiceWithName方法所产生的对象。
大致就是这样,这里也是ZendFramework 2为解耦合做的一些努力。
2. 事件驱动
在Zend Framework 2初始化的时候,会依据配置注冊各类事件并绑定事件处理函数。主要是由Zend\EventManager组件来实现的事件驱动。主要有两个核心文件,Event.php和EventManager.php。一个是事件类(Event.php),一个是事件管理器类(EventManager.php)。这个里面也定义了非常多接口以及一些共享事件管理器等。
EventManager类主要负责绑定(attach)事件、解除(detach)事件、触发事件(trigger)。在EventManager类内部。维护着一个事件数组。事件数组维护着事件名称与事件处理函数的一对多的相应关系,也就是说一个事件名称能够绑定多个事件处理函数,当事件被触发后,依照绑定顺序,依次运行所绑定的事件处理函数。事件处理函数也被称为监听器(Listener)。在Zend Framework2中实现了一个优先队列,绑定事件的时候,能够给该事件也绑定上运行顺序,这样就能保证在一对多的关系中,你能够设置事件的运行顺序。
Zend Framework 2中预先定义了一些不同的事件对象,如ModuleEvent、MvcEvent、ViewEvent、SendResponseEvent等,他们都继承于 Zend\EventManager\Event。这些不同的事件对象所起的作用事实上是一样的。都是在事件驱动的工作流程中把事件发生时的上下文信息传递给监听器(Listener),不同之处在于事件发生时的逻辑环境。不论什么程序在逻辑上总是会有不同的运行阶段的,在不同阶段的上下文环境是不同的。假设用一个事件对象来贯穿全部的运行阶段。必定会在该对象上附加全部阶段的上下文信息,从而导致该对象的臃肿,程序结构也不清晰。
因此这里的设计方法就是在不同的逻辑环境中,使用不同的事件对象。
Zend Framework 2在逻辑上把运行过程分成了两个部分,第一个部分是各模块和服务对象的初始化。第二部分是程序的运行。
首先我们来看看/public/index.php 这个入口文件。
主要就三行代码,前面两行主要是autoload,第三行进入程序的运行
Zend\Mvc\Application::init(require‘config/application.config.php‘)->run();
1. 初始化做了些什么
第一步,他产生了一个ServiceManager对象。
在ServiceManager初始化的时候默认注冊了两个工厂。各自是事件管理器工厂(EventManagerFactory)和模块管理器工厂(ModuleManageFactory)是在Zend\Mvc\Service\ServiceManagerConfig中注冊的。
后面我们会看到在另一个类中注冊了更多的服务对象。事件管理器工厂比較简单。仅仅创建一个事件管理器(EventManager)对象。该对象负责整个MVC流程中全部事件的绑定以及触发。而模块管理器工厂比較复杂,在创建模块管理器(ModuleManager)对象时。还绑定了模块初始化过程中的一些默认事件监听对象(Listener)。
接下来是module的载入,
模块(Module)初始化过程中。有四个事件(模块初始化事件)会被触发,依次是:
- loadModules(開始载入全部模块)
- loadModule.resolve(单个模块開始解析)
- loadModule(单个模块開始载入)
- loadModules.post(全部模块载入完毕)
以上这些事件定义在Zend\ModuleManager\ModuleEvent类中。在Zend Framework 2中,为这些事件绑定了很多默认的监听器(Listener)。大多数监听器的绑定由Zend\ModuleManager\Listener\DefaultListenerAggregate类完毕,它是一个默认监听器的聚合类。在loadModules的时候也绑定了非常多监听器。同一时候也默认注冊了非常多服务对象。
这样,当初始化阶段完毕后,会把全部模块(Module)文件夹下的ModuleConfig与全局的GlobConfig的内容合并成一个数组。GlobConfig会覆盖ModuleConfig下的同名内容。以Config为名字保存在ServiceLocator对象中,另外在ServiceLocator对象中另一条为ApplicationConfig的内容,保存的是 config/application.config.php的内容。
2.程序运行
当个模块初始化完毕之后。将进入程序的运行引导。以下这段就是进入程序的引导部分。
在这里Zend Framework 2将绑定一系列的监听器,比方RouteListener、DispatchListener、SendResponseListener、ViewManager。
RouteListener:为route事件绑定一个监听器。主要负责监听解析http请求中的url地址。
DispatchListener:为dispatch事件绑定了一个监听器。主要是负责监听依据解析之后的url地址,找到相应的controller,然后运行相应的action。
SendResponseListener:为finish事件绑定了一个监听器。该监听器用来产生ResponseEvent对象,并在该对象上触发一系列与发送相应请求(Response)有关的事件。
ViewManager:这个里面涉及到非常多东西,比方:变量的容器(Variables Containers)、视图模型(ViewModels)、视图助手(Helper)、模板(Template)、渲染策略(RenderStrategy)、脚本解析(Reslover)、响应策略(Response Strategy)等,在ViewManager中,为各类绑定了绑定了非常多模板处理相关监听器。
绑定完毕之后,開始出发事件的引导事件:MvcEvent::EVENT_BOOTSTRAP。引导完之后就開始运行run()方法。run()方法主要就是触发了四个事件:MvcEvent::EVENT_ROUTE、MvcEvent::EVENT_DISPATCH、 MvcEvent::EVENT_RENDER、MvcEvent::EVENT_FINISH。绑定在这些事件上的监听器会负责完毕MVC的整个流程。
6.性能效率
server 2U4G
以下是hello world程序,ZendFramework 2的程序流程图:
看上去非常复杂的样子。事实上本来就挺复杂(另存为能够放大看)。
精简一下,我们再来看看初始化中耗时比較高的一些方法
从上面的图,我们发现大部分时间花在了mvc的初始化。
以下我们来看看Zend Framework 2的QPS:
看这个数据还是挺慘的,QPS感觉有点低。不能充当大任啊。
7.总结
Zend Framework 2在性能方面表现的太让人失望了。可是他的设计理念还是挺好的,可是感觉有点设计过重,初始化的时候做了太多的事情。载入了太多的模块。导致运行效率不高,在实际生产中还是慎重使用。
-------------------------------------------------------------------------------------
黑夜路人,一个关注开源技术、乐于学习、喜欢分享的程序猿
博客:http://blog.csdn.net/heiyeshuwu
微博:http://weibo.com/heiyeluren
微信:heiyeluren2012
想获取更多IT开源技术相关信息,欢迎关注微信!
微信二维码扫描高速关注本号码: