1. 程式人生 > >【原創】Zend Framework 2框架之MVC

【原創】Zend Framework 2框架之MVC

spa lov gef rst 當前 mage 匿名函數 skeleton 一個

ZendFramework 2框架之MVC

作者:sys(360電商技術組)

技術分享技術分享技術分享1.前言

Zend Framework 2zend官方推出的php開源框架,基於php5.3。他全然採用面向對象的代碼實現,並利用了php5.3的一些新特性,比方命名空間。閉包等。由於是官方的推薦的,今天我們就來學習學習Zend Framework 2,由於本人知識淺薄,也沒有實際的用Zend Framework 2做項目開發的經驗。有錯誤的地方還請大家指正,也希望在後面的開發中能用用該框架,此篇文章權當拋磚引玉。


技術分享2.體會

相對於我們如今用的QFrameZendFramework 2讓我感覺還是相當復雜。可能QFrame我們僅僅用一天的時間。就能全然了解裏面的詳細實現。可是

Zend Framework 2看了幾天還是讓我無所適從。

讓我感覺QFrame非常實在,非常落地,學習使用相對easy,而Zend Framework 2就有點復雜了。Zend Framework 2MVC主要採用了Service Locator和事件驅動的設計模式。他提倡不論什麽類庫,擴展等資源都統一被視為服務對象。由一個管理者進行管理,全部服務對象都須要註冊給管理者。

當應用程序須要某些資源的時候,都從管理者中獲取資源。這樣的方法的優點在於解除了服務調用者和服務提供者之間的耦合。

Zend Framework 2中用了非常多設計模式,這一點,是自己須要提高的。在我們實際業務開發中,用的模式比較少,希望在這方面有所加強。

另一個,我的體會是,Zend Framework 2在編碼規範和凝視方面做的比較好。這讓我想起來了一篇文章,說谷歌為什麽嚴格運行代碼規範,大家開能夠看看:http://developer.51cto.com/art/201108/283275.htm

這裏說說Zend Framework 2的環境搭建以及Zend Framework 2mvc的形式,主要是一些網上和自己的一些使用心得。


技術分享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文件夾是放cssjsimg等的一下資源文件。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.phpEventManager.php。一個是事件類(Event.php),一個是事件管理器類(EventManager.php)。這個裏面也定義了非常多接口以及一些共享事件管理器等。

EventManager類主要負責綁定(attach)事件、解除(detach)事件、觸發事件(trigger)。在EventManager類內部。維護著一個事件數組。事件數組維護著事件名稱與事件處理函數的一對多的相應關系,也就是說一個事件名稱能夠綁定多個事件處理函數,當事件被觸發後,依照綁定順序,依次運行所綁定的事件處理函數。事件處理函數也被稱為監聽器(Listener)。在Zend Framework2中實現了一個優先隊列,綁定事件的時候,能夠給該事件也綁定上運行順序,這樣就能保證在一對多的關系中,你能夠設置事件的運行順序。

Zend Framework 2中預先定義了一些不同的事件對象,如ModuleEventMvcEventViewEventSendResponseEvent等,他們都繼承於 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將綁定一系列的監聽器,比方RouteListenerDispatchListenerSendResponseListenerViewManager

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_ROUTEMvcEvent::EVENT_DISPATCH MvcEvent::EVENT_RENDERMvcEvent::EVENT_FINISH。綁定在這些事件上的監聽器會負責完畢MVC的整個流程。


技術分享6.性能效率

server 2U4G

以下是hello world程序,ZendFramework 2的程序流程圖:

技術分享

看上去非常復雜的樣子。事實上本來就挺復雜(另存為能夠放大看)。

精簡一下,我們再來看看初始化中耗時比較高的一些方法

技術分享

從上面的圖,我們發現大部分時間花在了mvc的初始化。

以下我們來看看Zend Framework 2QPS

技術分享

看這個數據還是挺慘的,QPS感覺有點低。不能充當大任啊。


技術分享7.總結

Zend Framework 2在性能方面表現的太讓人失望了。可是他的設計理念還是挺好的,可是感覺有點設計過重,初始化的時候做了太多的事情。載入了太多的模塊。導致運行效率不高,在實際生產中還是慎重使用。



-------------------------------------------------------------------------------------

黑夜路人,一個關註開源技術、樂於學習、喜歡分享的程序猿


博客:http://blog.csdn.net/heiyeshuwu

微博:http://weibo.com/heiyeluren

微信:heiyeluren2012

想獲取更多IT開源技術相關信息,歡迎關註微信!

微信二維碼掃描高速關註本號碼:


技術分享



【原創】Zend Framework 2框架之MVC