2.1. YII的MVC模式
Yii 實現了 Web 編程中廣爲採用的「模型-視圖-控制器」(MVC)設計模式。MVC 致力於分離業務邏輯和用戶界面,這樣開發者能夠很容易地修改某個部分而不影響其它。在 MVC 中,模型表現信息(數據)和業務規則;視圖包含用戶界面中用到的元素,好比文本、表單輸入框;控制器管理模型和視圖間的交互。
除了 MVC,Yii 還引入了一個叫作 application 的前端控制器,它表現整個請求過程的運行環境。Application 接收用戶的請求並把它分發到合適的控制器做進一步處理。
下圖描述了一個 Yii 應用的靜態結構:
圖 1 Yii 應用的靜態結構
下圖描述了一個 Yii 應用處理用戶請求時的典型流程:
圖 2 Yii 應用的典型流程
1. 用戶訪問 http://www.example.com/index.php?r=post/show&id=1,Web 服務器執行入口腳本 index.php 來處理該請求。
2. 入口腳本創建一個應用實例並運行之。
3. 應用從一個叫 request 的應用部件得到詳細的用戶請求信息。
4. 經過 urlManager 這個應用部件,肯定用戶要請求的控制器和動做。
5. 應用創建一個被請求的控制器實例來進一步處理用戶請求,控制器肯定由它的actionShow 方法來處理 show 動做。而後它創建並應用和該動做相關的過濾器,若是過濾器容許的話,動做被執行。
6. 動做從數據庫讀取一個 ID 爲 1 的 Post 模型。
7. 動做使用 Post 模型來渲染一個叫 show 的視圖。
8. 視圖讀取 Post 模型的屬性並顯示之。
9. 視圖運行一些掛件。
10. 視圖的渲染結果嵌在佈局中。
11. 動做結束視圖渲染並顯示結果給用戶。
2.1.1. 調試模式
一個 Yii 應用可以根據 YII_DEBUG 常量的指示以調試模式或者生產模式運行。默認狀況下該常量定義爲 false,表明生產模式。要以調試模式運行,在包含 yii.php 文件前將此常量定義爲 true。應用以調試模式運行時效率較低,由於它會生成許多內部日誌。從另外一個角度來看,發生錯誤時調試模式會產生更多的調試信息,於是在開發階段很是有用。但在正式上線以後,則須要去掉調試模式,由於調試模式會打印不少額外信息,這些信息會在必定程度上影響其運行的性能。
2.2. 應用
應用表示一個請求處理的上下文。它的主要任務是分解用戶的請求而且把它分發到恰當的控制器中進行進一步的處理。它也保存應用級的配置,所以也被稱爲前端控制器。
默認狀況下,應用是 CWebApplication 類的一個實例。 要對其進行定製, 一般是在應用實例被建立的時候提供一個配置文件 (或數組) 來初始化其屬性值。 另外一個定製應用的方法就是擴展 CWebApplication 類。配置是一個鍵值對的數組。 每一個鍵名都對應應用實例的一個屬性, 相應的值爲屬性的初始值。 若是應用的配置很是複雜,也能夠將其分解成多個文件,每一個文件返回配置數組的一部分。
應用根目錄表示包含全部安全敏感的PHP腳本和數據的根目錄。缺省狀況下,它是包含入口腳本的目錄的名爲protected的子目錄。應當組織Web用戶訪問這個目錄。
能夠經過靈活的部件框架方便的進行應用功能的定製和擴展。應用管理着部件的集合,每一個部件實現特定的功能。例如,應用可能在CUrlManager 和 CHttpRequest的幫助下處理一個用戶的請求。
Yii預約義了一個核心部件集合來提供Web應用中的經常使用功能,下面是CWebApplication類中預約義 核心部件:
assetManager:CAssetManager - 管理私有資源文件的發佈
authManager:CAuthManager – 管理基於角色的訪問控制(RBAC)
cache:CCache – 提供數據緩存功能
clientScript:CClientScript – 管理客戶端腳本(javascript和CSS)
coreMessages:CPhpMessageSource – 提供Yii框架所使用的轉換過的核心消息
db:CDbConnection – 提供數據庫鏈接
errorHandler:CErrorHandler – 處理未被捕獲的PHP錯誤和異常
messages:CPhpMessageSource – 提供Yii應用使用的轉換過的消息
request:CHttpRequest – 提供和用戶請求相關的信息
securityManager:CSecurityManager – 提供安全相關的服務,如散列,加密
session:CHttpSession – 提供會話相關的功能
statePersister:CStatePersister – 提供全局持續狀態方法
urlManager:CUrlManager – 提供URL解析和建立功能
user:CWebUser – 表示當前用戶的身份信息
themeManager:CThemeManager – 管理主題
處理一個用戶請求時,一個應用將會經歷這樣一個生命週期:
1. 設置自動加載和錯誤處理類
2. 註冊核心應用部件
3. 加載應用配置
4. 使用CApplication::init()初始化應用
加載靜態應用部件
5. 觸發onBeginRequest事件
6. 處理用戶請求:
解析用戶請求
建立控制器
運行控制器
7. 觸發onEndRequest事件
2.3. 控制器
控制器是 CController 或者其子類的實例。 用戶請求應用時,建立控制器。 控制器執行請求action,action一般引入必要的模型並提供恰當的視圖。 最簡單的action僅僅是一個控制器類方法,此方法的名字以action開始。
控制器有默認的action。用戶請求沒指定哪個action執行時,將執行默認的action。 缺省狀況下,默認的action名爲index。能夠經過設置CController::defaultAction改變默認的action。
下邊是最小的控制器。由於控制器未定義任何action,請求時會拋出異常。
class SiteController extends CController
{
}
CWebApplication在處理一個新請求時,實例化一個控制器。程序經過控制器的ID,並按必定規則肯定控制器類及控制器類所在位置。
一個動做能夠定義爲一個函數或者一個動做類。當請求這個動做時,控制器實例化這個類。這樣就能夠複用和重用動做。
過濾器是配置爲控制器動做以前或以後執行的一段代碼。例如能夠設計一個性能過濾器用於計時動做執行的時間。一個動做能夠有多個過濾器。過濾器能夠定義爲控制器類的方法,也能夠是CFilter類的子類。
2.4. 模型
模型是 CModel 或其子類的實例。 模型用於保持數據以及和數據相關的業務規則。模型描述了一個單獨的數據對象。它能夠是數據表中的一行數據或者用戶輸入的一個表單。數據中的各個字段都描述了模型的一個屬性。這些屬性都有一個標籤,均可以被一套可靠的規則驗證。
Yii 從表單模型和 active record 實現了兩種模型。 它們都繼承自基類 CModel。
表單模型是CFormModel的實例。表單模型用於保存經過收集用戶輸入得來的數據。這樣的數據一般被收集,使用,而後被拋棄。例如,在一個登陸頁面上,咱們可使用一個表單模型來描述諸如用戶名,密碼這樣的由最終用戶提供的信息。
Active Record (AR) 是一種面向對象風格的,用於抽象數據庫訪問的設計模式。任何一個 AR 對象都是 CActiveRecord 或其子類的實例, 它描述的數據表中的單獨一行數據。這行數據中的字段被描述成 AR 對象的一個屬性。
2.5. 視圖
視圖是一個包含了主要的用戶交互元素的PHP腳本。他能夠包含PHP語句,可是建議這些語句不要去改變數據模型,且最好可以保持其單純性(單純做爲視圖)!爲了實現邏輯和界面分離,大部分的邏輯應該被放置於控制器或模型裏,而不是視圖裏。
視圖有一個當其被渲染(render)時用於校驗的名稱。視圖的名稱與其腳本名稱是同樣的。例如:視圖 edit 的名稱出自一個名爲 edit.php 的腳本文件。經過 CController::render() 調用視圖的名稱能夠渲染一個視圖。這個方法將在 protected/views/ControllerID 目錄下尋找對應的視圖文件。
在視圖腳本內部,能夠經過 $this 來訪問控制器實例。能夠在視圖裏以 $this->propertyName 的方式 pull 控制器的任何屬性。也能夠用如下 push 的方式傳遞數據到視圖裏:
$this->render('edit', array(
'var1'=>$value1,
'var2'=>$value2,
));
在以上的方式中, render() 方法將提取數組的兩個參數到變量裏。其產生的結果是,在視圖腳本里,咱們能夠直接訪問變量 $var1 和 $var2。
佈局是一種特殊的視圖文件用來修飾視圖。它一般包含了用戶交互過程當中經常使用到的一部分視圖。
組件是 CWidget 或其子類的實例。它是一個主要用於描述特定意圖的組成部分。組件一般內嵌於一個視圖來產生一些複雜卻獨立的用戶界面。例如,一個日曆組件能夠用於渲染一個複雜的日曆界面。組件能夠在用戶界面上更好的實現重用。
系統視圖的渲染一般用於展現 Yii 的錯誤和日誌信息。例如,當用戶請求來一個不存在的控制器或動做時,Yii 會拋出一個異常來解釋這個錯誤。 這時,Yii 就會使用一個特殊的系統視圖來展現這個錯誤。
2.6. 部件
Yii 應用構建於對象是規範編寫的部件之上。部件是 CComponent 或其衍生類的實例。使用部件主要就是涉及訪問其屬性和掛起/處理它的事件。基類 CComponent 指定了如何定義屬性和事件。
部件的屬性就像對象的公開成員變量,能夠被讀取或設置部件屬性。
部件事件是一種特殊的屬性,它能夠將方法(稱之爲事件句柄(event handlers))做爲它的值。綁定(分配)一個方法到一個事件將會致使方法在事件被掛起處自動被調用。所以部件行爲可能會被一種在部件開發過程當中不可預見的方式修改。部件事件以 on 開頭的命名方式定義。
部件能夠綁定一個或者多個行爲。一個行爲(behavior) 就是一個對象,其方法能夠被它綁定的部件經過收集功能的方式來實現 '繼承(inherited)',而不是專有化繼承(即普通的類繼承)。簡單的來講,就是一個部件能夠以'多重繼承'的方式實現多個行爲的綁定。
2.7. 開發流程
用yii開發一個web程序的基本流程,以下所示:
1. 建立目錄結構
2. 配置 application,即修改application配置文件
3. 每種類型的數據都建立一個 model 類來管理
4. 每種類型的用戶請求都建立一個 controller 類。 依據實際的需求對用戶請求進行分類。通常來講,若是一個model類須要用戶訪問,就應該對應一個controller類。
5. 實現 actions 和相應的 views。這是真正須要咱們編寫的工做。
6. 在controller類裏配置須要的action filters 。
7. 若是須要主題功能,編寫 themes。
8. 若是須要 internationalization國際化功能,編寫翻譯語句。
9. 使用 caching 技術緩存數據和頁面。
10. 最後調整好程序和發佈。
3. 測試考慮
Yii提供了自動化測試的方法,包括單元測試和功能測試,其中單元測試是驗證一個單元的代碼可以像預想的同樣工做,對於Yii來講,就是驗證類中的每一個方法均可以正確的工做,輸入不一樣的參數和數據,來驗證類中每一個方法可以輸出符合預期的數據和行爲。
功能測試是肯定一個功能、特徵(例如博客系統中的發表管理)能夠像預想的同樣工做。因爲一個功能可能包含多個類,所以相比較單元測試,功能測試在更高的級別。
Yii的測試框架是創建在PHPUnit之上的。
3.1. 定義Fixtures
一套自動化的case每每會被執行屢次。爲了保證這個測試的過程是可重複的,咱們須要在執行case的時候,讓其初始狀態是處於一個已知肯定的狀態。這個狀態,咱們叫作fixture,通俗的講,就是在測試以前所須要的環境的全部初始狀態。
創建一個數據庫的fixture在web應用開發過程當中多是一個最耗時的部分。Yii框架引入了一個叫作CDbFixtureManager的應用組件來緩和這個問題,大致來講,在執行一個測試集合時它作了這樣幾件事情:
在全部case運行前,它把與本次運行case相關的全部數據表置於一個已知的狀態。在一個單一的case運行前,它把一些特定的表復位到一個已知的狀態。
在執行一個方法的過程當中,它提供了對與這些fixture有關的數據的訪問。
爲了使用CDbFixtureManager這個類,通常會進行以下配置:
return array(
'components'=>array(
'fixture'=>array(
'class'=>'system.test.CDbFixtureManager',
),
),
);
對於這些咱們想提供做爲fixture的數據,通常會將其放在/protected/tests/fixtures目錄下。這些數據文件按照php的形式組織在一塊兒,統稱爲fixture file。每一個fixture file會返回一個數組,該數組包含一些特定的表的某些行的預設值。而且文件名跟表名保持一致。
3.2. 單元測試
咱們能夠總結出以下在Yii中書寫單元測試的原則:
● 單元測試是經過實現繼承自CTestCase或CDbTestCase類的XyzTest類來實現,其中Xyz表示要測試的類名。CTestCase用於通用單元測試而CDbTestCase用於活動記錄模型類的測試。因爲PHPUnit_Framework_TestCase是這兩個類的父類,所以咱們可使用繼承自此類的全部方法。
● 單元測試類以文件XyzTest.php的形式保存。爲了方便起見,通常單元測試的case會存儲在protected/tests/unit下。
● 測試類主要是一個待測試的類的方法的集合,若是這個待測試的類叫作Abc,那麼這個測試類通常會起名爲testAbc。
● 一個測試類常常包含一系列的斷言,(例如assertTrue, assertEquals),做爲驗證目標類行爲的檢驗點。
以如何爲active record模型類創建單測爲例,咱們來看看究竟如何寫一個單測case。
假設咱們想測試一個blog的評論模型類,首先要建立一個CommonTest.php並保存在/protected/tests/unit/CommentTest.php,代碼以下:
class CommentTest extends CDbTestCase
{
public $fixtures=array(
'posts'=>'Post',
'comments'=>'Comment',
);
......
}
在上述類中,咱們制定了fixture的成員變量是一個數組,該數組將會用戶接下來的測試case中。
Fixture names容許咱們在測試方法中以一種很是方便的方式來訪問fixture data。最典型的用法以下:
$comments = $this->comments;
接下來,咱們就能夠書寫textApprove方法來測試評論視圖類中的approve 方法了。
3.3. 功能測試
● 像單元測試同樣,功能測試時經過實現繼承自CWebTestCase類的XyzTest類來實現,其中Xyz表示要測試的類名。因爲 PHPUnit_Extensions_SeleniumTestCase是CwebTestCase的父類,所以能夠採用繼承自此類的全部方法。
● 功能測試類以文件XyzTest.php的形式保存。
● 測試類主要包含命名爲testABC的測試方法的集合,其中Abc常常是要測試的功能的名字,例如testLogin
● 一個測試方法常常包含一系列的指令來發出命令以與被測試Web應用交互。它也包含一些斷言狀態來驗證Web應用如預想同樣響應。
3.4. 其餘
3.4.1基於module的單元測試方法
有的yii版本不支持基於phpUnit 的單元的測試,那麼咱們也能夠有其餘的辦法來作單元測試。具體的方法就是把test做爲一個module。目錄部署結構爲:
webRoot/protected/modules/test/controller/ABC.php
在上述ABC.php裏,咱們能夠建立繼承自業務的類,並在這些類中構建對應的action,每一個action均可以調用須要測試的函數。經過在瀏覽器上直接請求這些action,並打印出相關信息,便可實現對上述這些函數的測試。如想測試的action函數爲actionAdd。
根據yii的url解析規則,上述Add方法的調用即爲該url的請求http://*.*.*.*/index.php?r=test/ABC/Add 。 若是適當的加上返回結果的展示,那麼就能很明確的知道該函數的返回值與預期的是否相符。
3.4.2Firebug輔助測試
Firebug也是當今web開發程序員的一個利器,同時也能夠做爲測試人員的一個參考。Firebug會記錄各個請求的參數,post數據,響應數據。當功能出現問題時,測試人員能夠根據事先設計的參數和預期的返回的數據來斷定是view傳遞的參數錯誤,仍是php根據邏輯所計算出的返回數據值不對。從而來定位錯誤的真正位置。
(全文完)
做者:mimical
來自:
http://hi.baidu.com/baiduqa/blog/item/271d1a5313886a15367abecd.html