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开源技术相关信息,欢迎关注微信!

微信二维码扫描高速关注本号码:

【原创】Zend Framework 2框架之MVC的更多相关文章

  1. zend framework分析总结[转]

    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版.作者信息和本声明.否则将追究法律责任.http://blog.csdn.net/mayongzhan - 马永占,myz,may ...

  2. 主流PHP框架间的比较(Zend Framework,CakePHP,CodeIgniter,Symfony,ThinkPHP,FleaPHP)

    Zend Framework 优点: Zend Framework大量应用了PHP5中面向对象的新特征:接口.异常.抽象类.SPL等等.这些东西的应用让Zend Framework具有高度的模块化和灵 ...

  3. Zend Framework MVC的结构

    The Zend Framework MVC Architecture 一.概述: In this chapter, we will cover the following topics:1. Zen ...

  4. 搭建PHP官方框架zend framework 2(LINUX)

    在五花八门的语言里,PHP作为我第一个觉得欣赏的理由,就是它的简单和快捷,因为它封装了许多的常用函数.PHP作为网站中一种算作比较流行的语言,也产生各种优秀的框架.我所接触过的有zend framew ...

  5. 高性能Web框架Zend Framework

    Zend Framework (ZF)是用 PHP 5.3及更高版本来开发 Web 程序和服务的开源框架.ZF用100% 面向对象编码实现. ZF的组件结构独一无二,每个组件几乎不依靠其他组件.这样的 ...

  6. Getting Started with Zend Framework MVC Applications

    Getting Started with Zend Framework MVC Applications This tutorial is intended to give an introducti ...

  7. Zend Framework 框架搭建

    通过手工方法搭建Zend Framework的MVC框架结构.首先看一下zend framework mvc的目录结构 1. 在根目录下面创建 public ,并在 public 下创建 index. ...

  8. zend framework框架学习走起——从零开始,点击记录-安装

    zend framework第一步,先来安装下zend framework框架. 先介绍下,我这边的php配置环境,为图省事,我是安装wampserver来搭载php环境的,,php+Apache+m ...

  9. Zend Framework 2中如何使用Service Manager

    end Framework 2 使用ServiceManager(简称SM)来实现控制反转(IoC).有很多资料介绍了service managers的背景,我推荐大家看看this blog post ...

随机推荐

  1. VC 对话框程序加入工具栏button图标及其buttontooltip

    注意:本人使用VC++2010开发环境进行測试. 在使用VC开发对话框程序时不像开发单文档程序和多文档程序那么方便,非常多资源都须要自己手动加入.近期在开发一个程序时.想尝试在对话框程序里面加入 工具 ...

  2. Oracle动态性能表-V$SESSION_WAIT,V$SESSION_EVENT

    (1)-V$SESSION_WAIT 这是一个寻找性能瓶颈的关键视图.它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什么也没在做,则显示它最后的等待事件).当系统存 ...

  3. oracle 11gR2 如何修改 private ip

    1.1    修改 private ip1.1.1  确保crs集群是打开的可以用olsnodes –s 检查集群的状态./olsnodes -sP570a ActiveP570b Active1.1 ...

  4. 求包含每个有序数组(共k个)至少一个元素的最小区间

    title: 求包含每个有序数组(共k个)至少一个元素的最小区间 toc: false date: 2018-09-22 21:03:22 categories: OJ tags: 归并 给定k个有序 ...

  5. ROS-SLAM仿真-cartographer

    前言:cartographer是谷歌2016年发布的一个开源slam算法,采用基于图网络的优化方法,主要基于激光雷达来实现. 使用源码编译方式. 一.新建工作空间 1.1 使用roboware新建名为 ...

  6. 什么时候使用try-catch

    上篇文章叙述了try-catch的效率问题,以及StackOverflow上各路大神们指出使用try-catch应该注意的一些问题. 这篇文章作为补充,转述下StackOverflow上各路大神对于何 ...

  7. usaco 最少找零

    Description 约翰在镇上买了 T 元钱的东西,正在研究如何付钱.假设有 N 种钞票,第 i 种钞票的面值为 Vi,约翰身上带着这样的钞票 Ci 张.商店老板罗伯是个土豪,所有种类的钞票都有无 ...

  8. 移动端ios升级到11及以上时,手机弹框输入光标出现错位问题

    引起原因:弹框的定位采取position:fixed,而ios(safari)对定位属性position:fixed的解析不一致导致. 解决方案: 方案一 一开始上网找解决方案,找到如下处理方式.但存 ...

  9. CommandType.Text

    CommandType.Text代表执行的是SQL语句CommandType.StoreProcedure代表执行的是存储过程CommandType代表要执行的类型 //返回DataTable的SQL ...

  10. Dynamic dispatch mechanisms

    Normally, in a typed language, the dispatch mechanism will be performed based on the type of the arg ...