ZendFramework 2框架之MVCphp
做者:sys(360電商技術組)css
Zend Framework 2是zend官方推出的php開源框架,基於php5.3。他全然採用面向對象的代碼實現,並利用了php5.3的一些新特性,比方命名空間。閉包等。因爲是官方的推薦的,今天咱們就來學習學習Zend Framework 2,因爲本人知識淺薄,也沒有實際的用Zend Framework 2作項目開發的經驗。有錯誤的地方還請你們指正,也但願在後面的開發中能用用該框架,此篇文章權當拋磚引玉。設計模式
相對於咱們現在用的QFrame,ZendFramework 2讓我感受仍是至關複雜。可能QFrame咱們僅僅用一天的時間。就能全然瞭解裏面的詳細實現。但是Zend Framework 2看了幾天仍是讓我無所適從。數組
讓我感受QFrame很是實在,很是落地,學習使用相對easy,而Zend Framework 2就有點複雜了。Zend Framework 2的MVC主要採用了Service Locator和事件驅動的設計模式。他提倡不論什麼類庫,擴展等資源都統一被視爲服務對象。由一個管理者進行管理,所有服務對象都需要註冊給管理者。微信
當應用程序需要某些資源的時候,都從管理者中獲取資源。這樣的方法的優勢在於解除了服務調用者和服務提供者之間的耦合。閉包
Zend Framework 2中用了很是多設計模式,這一點,是本身需要提升的。在咱們實際業務開發中,用的模式比較少,但願在這方面有所增強。mvc
另外一個,個人體會是,Zend Framework 2在編碼規範和凝視方面作的比較好。這讓我想起來了一篇文章,說谷歌爲何嚴格運行代碼規範,你們開可以看看:http://developer.51cto.com/art/201108/283275.htm。app
這裏說說Zend Framework 2的環境搭建以及Zend Framework 2的mvc的形式,主要是一些網上和本身的一些使用心得。框架
我是依照官方的教程搭建的。函數
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的形式。第三種是下載壓縮包。我用的是最原始的方法,下載壓縮包。下載完以後,你把它放到你喜歡的文件夾。
好,現在來看一下咱們下載的一個演示樣例模板
大概的文件夾結構就是這樣的,入口是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的時候,文件夾結構也需要是類似的一個形式。
上面說到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的整個流程。
server 2U4G
如下是hello world程序,ZendFramework 2的程序流程圖:
看上去很是複雜的樣子。事實上原本就挺複雜(另存爲可以放大看)。
精簡一下,咱們再來看看初始化中耗時比較高的一些方法
從上面的圖,咱們發現大部分時間花在了mvc的初始化。
如下咱們來看看Zend Framework 2的QPS:
看這個數據仍是挺慘的,QPS感受有點低。不能充當大任啊。
Zend Framework 2在性能方面表現的太讓人失望了。但是他的設計理念仍是挺好的,但是感受有點設計太重,初始化的時候作了太多的事情。載入了太多的模塊。致使運行效率不高,在實際生產中仍是慎重使用。
-------------------------------------------------------------------------------------
黑夜路人,一個關注開源技術、樂於學習、喜歡分享的程序猿
博客:http://blog.csdn.net/heiyeshuwu
微博:http://weibo.com/heiyeluren
微信:heiyeluren2012
想獲取更多IT開源技術相關信息,歡迎關注微信!
微信二維碼掃描高速關注本號碼: