本文講述了Yii快速入門教程。分享給大家供大家參考,具體如下:
Ⅰ、基本概念
一、入口文件
入口文件內(nèi)容:一般格式如下:
<?php$yii=dirname(__FILE__).'/../../framework/yii.php';//Yii框架位置$config=dirname(__FILE__).'/protected/config/main.php';//當(dāng)前應(yīng)用程序的主配置文件位置// 部署正式環(huán)境時(shí),去掉下面這行// defined('YII_DEBUG') or define('YII_DEBUG',true);//是否運(yùn)行在調(diào)試模式下require_once($yii);//包含Yii框架Yii::createWebApplication($config)->run();//根據(jù)主配置文件建立應(yīng)用實(shí)例,并運(yùn)行。你可以在當(dāng)前應(yīng)用的任何位置通過Yii::app()來訪問這個(gè)實(shí)例。
二、主配置文件
保存位置:你的應(yīng)用/protected/config/main.php
文件內(nèi)容:一般格式如下:
<?phpreturn array('basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', //當(dāng)前應(yīng)用根目錄的絕對(duì)物理路徑'name'=>'Yii Blog Demo', //當(dāng)前應(yīng)用的名稱// 預(yù)載入log(記錄)應(yīng)用組件,這表示該應(yīng)用組件無論它們是否被訪問都要被創(chuàng)建。該應(yīng)用的參數(shù)配置在下面以“components”為關(guān)鍵字的數(shù)組中設(shè)置。'preload'=>array('log'), //log為組件ID// 自動(dòng)載入的模型和組件類'import'=>array('application.models.*', //載入“application/models/”文件夾下的所有模型類'application.components.*', //載入“application/components/”文件夾下的所有應(yīng)用組件類),'defaultController'=>'post', //設(shè)置默認(rèn)控制器類// 當(dāng)前應(yīng)用的組件配置。更多可供配置的組件詳見下面的“核心應(yīng)用組件”'components'=>array('user'=>array( //user(用戶)組件配置,“user”為組件ID// 可以使用基于cookie的認(rèn)證'allowAutoLogin'=>true, //允許自動(dòng)登錄),'cache'=>array( //緩存組件'class'=>'CMemCache', //緩存組件類'servers'=>array( //MemCache緩存服務(wù)器配置array('host'=>'server1', 'port'=>11211, 'weight'=>60), //緩存服務(wù)器1array('host'=>'server2', 'port'=>11211, 'weight'=>40), //緩存服務(wù)器2),),'db'=>array( //db(數(shù)據(jù)庫(kù))組件配置,“db”為組件ID'connectionString' => 'sqlite:protected/data/blog.db', //連接數(shù)據(jù)庫(kù)的DSN字符串'tablePrefix' => 'tbl_', //數(shù)據(jù)表前綴),// 如果要使用一個(gè)MySQL數(shù)據(jù)庫(kù),請(qǐng)取消下面的注釋'errorHandler'=>array(// 使用SiteController控制器類中的actionError方法顯示錯(cuò)誤'errorAction'=>'site/error', //遇到錯(cuò)誤時(shí),運(yùn)行的操作。控制器名和方法名均小寫,并用斜線“/”隔開),//URL路由管理器'urlManager'=>array('urlFormat'=>'path', //URL格式。共支持兩種格式:'path'格式(如:/path/to/EntryScript.php/name1/value1/name2 /value2...)和'get'格式(如: /path/to/EntryScript.php?name1=value1&name2=value2...)。當(dāng)使用'path'格式時(shí),需要設(shè)置如下的規(guī)則:'rules'=>array( //URL規(guī)則。語(yǔ)法:<參數(shù)名:正則表達(dá)式>'post/<id:/d+>/<title:.*?>'=>'post/view', //將post/12/helloword指向post/view?id=12&title=helloword'posts/<tag:.*?>'=>'post/index', //將posts/hahahaha指向post/index?tag=hahahaha'<controller:/w+>/<action:/w+>'=>'<controller>/<action>',),),'log'=>array( //記錄'class'=>'CLogRouter', //處理記錄信息的類'routes'=>array(array('class'=>'CFileLogRoute', //處理錯(cuò)誤信息的類'levels'=>'error, warning', //錯(cuò)誤等級(jí)),// 如要將錯(cuò)誤記錄消息在網(wǎng)頁(yè)上顯示,取消下面的注釋即可),),), //應(yīng)用組件配置結(jié)束// 使用Yii::app()->params['參數(shù)名']可以訪問應(yīng)用層的參數(shù)'params'=>require(dirname(__FILE__).'/params.php'),);
核心應(yīng)用組件:
Yii 預(yù)定義了一系列核心應(yīng)用組件,提供常見 Web 應(yīng)用中所用的功能。例如, request 組件用于解析用戶請(qǐng)求并提供例如 URL,cookie 等信息。通過配置這些核心組件的屬性,我們可以幾乎任意的修改Yii 的默認(rèn)行為。
下面我們列出了由 CWebApplication 預(yù)定義的核心組件。
assetManager: CAssetManager - 管理私有資源文件的發(fā)布。
authManager: CAuthManager - 管理基于角色的訪問控制 (RBAC).
cache: CCache - 提供數(shù)據(jù)緩存功能。注意,你必須指定實(shí)際的類(例如CMemCache, CDbCache)。否則,當(dāng)你訪問此組件時(shí)將返回 NULL。
clientScript: CClientScript - 管理客戶端腳本 (javascripts 和 CSS).
coreMessages: CPhpMessageSource - 提供 Yii 框架用到的核心信息的翻譯。
db: CDbConnection - 提供數(shù)據(jù)庫(kù)連接。注意,使用此組件你必須配置其 connectionString 屬性。
errorHandler: CErrorHandler - 處理未捕獲的 PHP 錯(cuò)誤和異常。
format: CFormatter - 格式化數(shù)值顯示。此功能從版本 1.1.0 起開始提供。
messages: CPhpMessageSource - 提供Yii應(yīng)用中使用的信息翻譯。
request: CHttpRequest - 提供關(guān)于用戶請(qǐng)求的信息。
securityManager: CSecurityManager - 提供安全相關(guān)的服務(wù),例如散列,加密。
session: CHttpSession - 提供session相關(guān)的功能。
statePersister: CStatePersister - 提供全局狀態(tài)持久方法。
urlManager: CUrlManager - 提供 URL 解析和創(chuàng)建相關(guān)功能
user: CWebUser - 提供當(dāng)前用戶的識(shí)別信息。
themeManager: CThemeManager - 管理主題。
要訪問一個(gè)應(yīng)用組件,使用 Yii::app()->組件的ID
三、控制器(Controller)
控制器 是 CController 類的子類的實(shí)例。它在當(dāng)用戶請(qǐng)求時(shí)由應(yīng)用創(chuàng)建。當(dāng)一個(gè)控制器運(yùn)行時(shí),它執(zhí)行所請(qǐng)求的動(dòng)作(控制器類方法),動(dòng)作通常會(huì)引入所必要的模型并渲染相應(yīng)的視圖。動(dòng)作,就是一個(gè)名字以 action 開頭的控制器類方法(action+大寫首字母的動(dòng)作名)。
控制器類文件保存位置protected/controllers/
控制器和動(dòng)作以 ID 識(shí)別。
控制器ID 是一種 '父目錄/子目錄/控制器名' 的格式,對(duì)應(yīng)相應(yīng)的控制器類文件 protected/controllers/父目錄/子目錄/大寫首字母的控制器名Controller.php;
動(dòng)作ID 是除去 action 前綴的動(dòng)作方法名。
1、路由
用戶以路由的形式請(qǐng)求特定的控制器和動(dòng)作。路由是由控制器 ID 和動(dòng)作 ID 連接起來的,兩者以斜線分割。
例如,路由 post/edit 代表 PostController 及其 edit 動(dòng)作。默認(rèn)情況下,URL http://hostname/index.php?r=post/edit 即請(qǐng)求此控制器和動(dòng)作。
注意: 默認(rèn)情況下,路由是大小寫敏感的。可以通過設(shè)置應(yīng)用配置中的 CUrlManager::caseSensitive 為 false 使路由對(duì)大小寫不敏感。當(dāng)在大小寫不敏感模式中時(shí), 要確保你遵循了相應(yīng)的規(guī)則約定,即:包含控制器類文件的目錄名小寫,且 控制器映射 和動(dòng)作映射 中使用的鍵為小寫。
路由的格式:控制器ID/動(dòng)作ID 或 模塊ID/控制器ID/動(dòng)作ID(如果是嵌套模塊,模塊ID 就是父模塊ID/子模塊ID)
2、控制器實(shí)例化
應(yīng)用將使用如下規(guī)則確定控制器的類以及類文件的位置:
① 、如果指定了 CWebApplication::catchAllRequest , 控制器將基于此屬性創(chuàng)建,而用戶指定的控制器 ID 將被忽略。這通常用于將應(yīng)用設(shè)置為維護(hù)狀態(tài)并顯示一個(gè)靜態(tài)提示頁(yè)面。
② 、如果在 CWebApplication::controllerMap 中找到了 ID, 相應(yīng)的控制器配置將被用于創(chuàng)建控制器實(shí)例。
③ 、如果 ID 為 'path/to/xyz'的格式,控制器類的名字將判斷為 XyzController,相應(yīng)的類文件則為 protected/controllers/path/to/XyzController.php。如果類文件不存在,將觸發(fā)一個(gè) 404 CHttpException 異常。
在使用了模塊的情況下,應(yīng)用將檢查此 ID 是否代表一個(gè)模塊中的控制器。如果是的話,模塊實(shí)例將被首先創(chuàng)建,然后創(chuàng)建模塊中的控制器實(shí)例。
3、動(dòng)作(action)
動(dòng)作 就是被定義為一個(gè)以 action 單詞作為前綴命名的方法。而更高級(jí)的方式是定義一個(gè)動(dòng)作類并讓控制器在收到請(qǐng)求時(shí)將其實(shí)例化。這使得動(dòng)作可以被復(fù)用,提高了可復(fù)用度。
1、定義一個(gè)動(dòng)作類,基本格式如下:
class UpdateAction extends CAction{public function run(){// place the action logic here}}
2、使用動(dòng)作類:為了讓控制器注意到這個(gè)動(dòng)作,我們要用如下方式覆蓋控制器類的actions() 方法:
class PostController extends CController{public function actions(){return array('edit'=>'application.controllers.post.UpdateAction', //使用“應(yīng)用程序文件夾/controllers/post/UpdateAction.php”文件中的類來處理edit動(dòng)作);}}
如上所示,我們使用了路徑別名“application.controllers.post.UpdateAction”指定動(dòng)作類文件為“protected/controllers/post/UpdateAction.php”。
通過編寫基于類的動(dòng)作,我們可以將應(yīng)用組織為模塊的風(fēng)格。例如,如下目錄結(jié)構(gòu)可用于組織控制器相關(guān)代碼:
protected/
controllers/
PostController.php
UserController.php
post/
CreateAction.php
ReadAction.php
UpdateAction.php
user/
CreateAction.php
ListAction.php
ProfileAction.php
UpdateAction.php
4、過濾器(filter)
過濾器是一段代碼,可被配置在控制器動(dòng)作執(zhí)行之前或之后執(zhí)行。
一個(gè)動(dòng)作可以有多個(gè)過濾器。如有多個(gè)過濾器,則按照它們出現(xiàn)在過濾器列表中的順序依次執(zhí)行。過濾器可以阻止動(dòng)作及后面其他過濾器的執(zhí)行。
過濾器可以定義為一個(gè)控制器類的方法。過濾器方法名必須以 filter 開頭。例如,現(xiàn)有的 filterAccessControl 方法定義了一個(gè)名為 accessControl 的過濾器。過濾器方法必須為如下結(jié)構(gòu):
public function filterAccessControl($filterChain){// 調(diào)用 $filterChain->run() 以繼續(xù)后續(xù)過濾器與動(dòng)作的執(zhí)行。}
$filterChain (過濾器鏈)是一個(gè) CFilterChain 的實(shí)例,代表與所請(qǐng)求動(dòng)作相關(guān)的過濾器列表。在過濾器方法中,我們可以調(diào)用 $filterChain->run() 以繼續(xù)執(zhí)行后續(xù)過濾器和動(dòng)作。
如 動(dòng)作 一樣,過濾器也可以是一個(gè)對(duì)象,它是 CFilter 或其子類的實(shí)例。如下代碼定義了一個(gè)新的過濾器類:
class PerformanceFilter extends CFilter{protected function preFilter($filterChain){// 動(dòng)作被執(zhí)行之前應(yīng)用的邏輯return true; // 如果動(dòng)作不應(yīng)被執(zhí)行,此處返回 false}protected function postFilter($filterChain){// 動(dòng)作執(zhí)行之后應(yīng)用的邏輯}}
要對(duì)動(dòng)作應(yīng)用過濾器,我們需要覆蓋 CController::filters() 方法。此方法應(yīng)返回一個(gè)過濾器配置數(shù)組。例如:
class PostController extends CController{......public function filters(){return array('postOnly + edit, create', //將postOnly過濾器應(yīng)用于edit和create動(dòng)作(這是基于方法的過濾器)array( //使用了數(shù)組來配置過濾器'application.filters.PerformanceFilter - edit, create', //將application.filters.PerformanceFilter過濾器應(yīng)用于除了edit和create之外的所有動(dòng)作(這是基于對(duì)象的過濾器)'unit'=>'second', //初始化過濾器對(duì)象中的unit屬性值為second),);}}
上述代碼指定了兩個(gè)過濾器: postOnly 和 PerformanceFilter。 postOnly 過濾器是基于方法的(相應(yīng)的過濾器方法已在 CController 中定義);而 performanceFilter 過濾器是基于對(duì)象的。路徑別名 application.filters.PerformanceFilter 指定過濾器類文件是 protected/filters/PerformanceFilter。我們使用一個(gè)數(shù)組配置 PerformanceFilter ,這樣它就可被用于初始化過濾器對(duì)象的屬性值。此處 PerformanceFilter 的 unit 屬性值將被初始為 second。
使用加減號(hào),我們可指定哪些動(dòng)作應(yīng)該或不應(yīng)該應(yīng)用過濾器。上述代碼中, postOnly 應(yīng)只被應(yīng)用于 edit 和 create 動(dòng)作,而 PerformanceFilter 應(yīng)被應(yīng)用于 除了 edit 和 create 之外的動(dòng)作。如果過濾器配置中沒有使用加減號(hào),則此過濾器將被應(yīng)用于所有動(dòng)作。
五、模型(Model)
模型是 CModel 或其子類的實(shí)例。模型用于保持?jǐn)?shù)據(jù)以及與其相關(guān)的業(yè)務(wù)邏輯。
模型是單獨(dú)的數(shù)據(jù)對(duì)象。它可以是數(shù)據(jù)表中的一行,或者一個(gè)用戶輸入的表單。
數(shù)據(jù)對(duì)象的每個(gè)字段對(duì)應(yīng)模型中的一個(gè)屬性。每個(gè)屬性有一個(gè)標(biāo)簽(label),并且可以通過一系列規(guī)則進(jìn)行驗(yàn)證。
Yii 實(shí)現(xiàn)了兩種類型的模型:表單模型和 Active Record。二者均繼承于相同的基類 CModel。
表單模型是 CFormModel 的實(shí)例。表單模型用于保持從用戶的輸入獲取的數(shù)據(jù)。這些數(shù)據(jù)經(jīng)常被獲取,使用,然后丟棄。例如,在一個(gè)登錄頁(yè)面中,我們可以使用表單模型用于表示由最終用戶提供的用戶名和密碼信息。
Active Record (AR) 是一種用于通過面向?qū)ο蟮娘L(fēng)格抽象化數(shù)據(jù)庫(kù)訪問的設(shè)計(jì)模式。每個(gè) AR 對(duì)象是一個(gè) CActiveRecord 或其子類的實(shí)例。代表數(shù)據(jù)表中的一行。行中的字段對(duì)應(yīng) AR 對(duì)象中的屬性。
六、視圖
視圖是一個(gè)包含了主要的用戶交互元素的PHP腳本.
視圖有一個(gè)名字,當(dāng)渲染(render)時(shí),名字會(huì)被用于識(shí)別視圖腳本文件。視圖的名稱與其視圖腳本名稱是一樣的。例如:視圖 edit 的名稱出自一個(gè)名為 edit.php 的腳本文件。要渲染時(shí),需通過傳遞視圖的名稱調(diào)用 CController::render()。這個(gè)方法將在“protected/views/控制器ID”目錄下尋找對(duì)應(yīng)的視圖文件。
在視圖腳本內(nèi)部,我們可以通過 $this 來訪問控制器實(shí)例。我們可以在視圖里以“$this->屬性名”的方式獲取控制器的任何屬性。
我們也可以用以下 推送 的方式傳遞數(shù)據(jù)到視圖里:
$this->render('edit', array('var1'=>$value1,'var2'=>$value2,));
在以上的方式中, render() 方法將提取數(shù)組的第二個(gè)參數(shù)到變量里。其產(chǎn)生的結(jié)果是,在視圖腳本里,我們可以直接訪問變量 $var1 和 $var2。
1、布局
布局是一種用來修飾視圖的特殊的視圖文件。它通常包含了用戶界面中通用的一部分視圖。例如:布局可以包含header和footer的部分,然后把內(nèi)容嵌入其間。
......header here......<?php echo $content; ?>......footer here......
其中的 $content 則儲(chǔ)存了內(nèi)容視圖的渲染結(jié)果。
當(dāng)使用render()時(shí),布局被隱式應(yīng)用。視圖腳本 protected/views/layouts/main.php 是默認(rèn)的布局文件。這可以通過改變 CWebApplication::layout 進(jìn)行自定義。要渲染一個(gè)不帶布局的視圖,則需調(diào)用 renderPartial() 。
2、小物件
小物件是 CWidget 或其子類的實(shí)例。它是一個(gè)主要用于表現(xiàn)數(shù)據(jù)的組件。小物件通常內(nèi)嵌于一個(gè)視圖來產(chǎn)生一些復(fù)雜而獨(dú)立的用戶界面。例如,一個(gè)日歷小物件可用于渲染一個(gè)復(fù)雜的日歷界面。小物件使用戶界面更加可復(fù)用。
我們可以按如下視圖腳本來使用一個(gè)小物件:
<?php $this->beginWidget('小物件類的路徑別名'[,'包含屬性初始化值的數(shù)組']); ?>...可能會(huì)由小物件獲取的內(nèi)容主體...<?php $this->endWidget(); ?>
或者
<?php $this->widget('小物件類的路徑別名'[,'包含屬性初始化值的數(shù)組']); ?>
后者用于不需要任何 body 內(nèi)容的組件。
小物件可通過配置來定制它的表現(xiàn)。這是通過調(diào)用 CBaseController::beginWidget 或 CBaseController::widget 設(shè)置其初始化屬性值來完成的。
我們通過傳遞一個(gè)攜帶這些屬性初始化值的數(shù)組來實(shí)現(xiàn),該數(shù)組的鍵是屬性的名稱,而數(shù)組的值則是小物件屬性所對(duì)應(yīng)的值。如下所示 :
<?php$this->widget('CMaskedTextField',array('mask'=>'99/99/9999'));?>
繼承 CWidget 并覆蓋其init()和run()方法,可以定義一個(gè)新的小物件:
class MyWidget extends CWidget{public function init(){// 此方法會(huì)被 CController::beginWidget() 調(diào)用}public function run(){// 此方法會(huì)被 CController::endWidget() 調(diào)用}}
小物件可以像一個(gè)控制器一樣擁有它自己的視圖。
默認(rèn)情況下,小物件的視圖文件位于包含了小物件類文件目錄的 views 子目錄之下(protected/components/views)。這些視圖可以通過調(diào)用CWidget::render()渲染,這一點(diǎn)和控制器很相似。唯一不同的是,小物件的視圖沒有布局文件支持。另外,小物件視圖中的$this指向小物件實(shí)例而不是控制器實(shí)例。
3、系統(tǒng)視圖
系統(tǒng)視圖的渲染通常用于展示 Yii 的錯(cuò)誤和日志信息。
系統(tǒng)視圖的命名遵從了一些規(guī)則。比如像“errorXXX”這樣的名稱就是用于渲染展示錯(cuò)誤號(hào)XXX的 CHttpException 的視圖。例如,如果 CHttpException 拋出一個(gè)404錯(cuò)誤,那么 error404 就會(huì)被顯示。
在 framework/views 下, Yii 提供了一系列默認(rèn)的系統(tǒng)視圖. 他們可以通過在 protected/views/system 下創(chuàng)建同名視圖文件進(jìn)行自定義。
七、組件
Yii 應(yīng)用建立于組件之上。組件是 CComponent 或其子類的實(shí)例。使用組件主要涉及訪問它的屬性以及觸發(fā)或處理它的時(shí)間。基類 CComponent 指定了如何定義屬性和事件。
1、組件屬性
組件的屬性就像對(duì)象的公共成員變量。它是可讀寫的。
要定義一個(gè)組件屬性,我們只需在組件類中定義一個(gè)公共成員變量即可。
更靈活的方式是定義其 getter 和 setter 方法,例如:
public function getTextWidth() // 獲取 textWidth 屬性{return $this->_textWidth;}public function setTextWidth($value) // 設(shè)置 TextWidth 屬性{$this->_textWidth=$value;}
上述代碼定義了一個(gè)可寫的屬性名為 textWidth(名字是大小寫不敏感的)。當(dāng)讀取屬性時(shí),getTextWidth() 就會(huì)被調(diào)用,其返回值則成為屬性值;相似的,當(dāng)寫入屬性時(shí),setTextWidth() 被調(diào)用。如果 setter 方法沒有定義,則屬性將是只讀的,如果對(duì)其寫入則會(huì)拋出一個(gè)異常。使用 getter 和 setter 方法定義一個(gè)屬性有一個(gè)好處:即當(dāng)讀取或?qū)懭雽傩詴r(shí),可以執(zhí)行額外的邏輯(例如,執(zhí)行驗(yàn)證,觸發(fā)事件)。
注意: 通過 getter/setter 定義的屬性和類成員變量之間有一個(gè)細(xì)微的差異:屬性的名字是大小寫不敏感的, 而 類成員變量是大小寫敏感的。
2、組件事件
組件事件是一些特殊的屬性,它們使用一些稱作 事件句柄(event handlers)的方法作為其值。分配一個(gè)方法到一個(gè)事件將會(huì)引起方法在事件被喚起處自動(dòng)被調(diào)用。因此,一個(gè)組件的行為可能會(huì)被一種在部件開發(fā)過程中不可預(yù)見的方式修改。
組件事件以 on 開頭的命名方式定義。和屬性通過 getter/setter 方法來定義的命名方式一樣,事件的名稱是大小寫不敏感的。以下代碼定義了一個(gè) onClicked 事件:
public function onClicked($event){$this->raiseEvent('onClicked', $event);}
這里作為事件參數(shù)的 $event 是 CEvent 或其子類的實(shí)例。
我們可以分配一個(gè)方法到此事件,如下所示:
這里的 $callback 指向了一個(gè)有效的 PHP 回調(diào)。它可以是一個(gè)全局函數(shù)也可以是類中的一個(gè)方法。如果是后者,它必須以一個(gè)數(shù)組的方式提供: array($object,'methodName')。
事件句柄的結(jié)構(gòu)如下:
function 方法名($event){......}
這里的 $event 即描述事件的參數(shù)(它來源于 raiseEvent() 調(diào)用)。$event 參數(shù)是 CEvent 或其子類的實(shí)例。至少,它包含了關(guān)于誰(shuí)觸發(fā)了此事件的信息。
事件句柄也可以是一個(gè)PHP 5.3以后支持的匿名函數(shù)。例如:
$component->onClicked=function($event) {......}
如果我們現(xiàn)在調(diào)用 onClicked(),onClicked 事件將被觸發(fā)(在 onClicked() 中),附屬的事件句柄將被自動(dòng)調(diào)用。
一個(gè)事件可以綁定多個(gè)句柄。當(dāng)事件觸發(fā)時(shí),這些句柄將被按照它們綁定到事件時(shí)的順序依次執(zhí)行。如果句柄決定組織后續(xù)句柄被執(zhí)行,它會(huì)設(shè)置 $event->handled 為 true。
3、組件行為
組件已添加了對(duì) mixin 的支持,并可以綁定一個(gè)或多個(gè)行為。行為是一個(gè)對(duì)象,其方法可以被它綁定的部件通過收集功能的方式來實(shí)現(xiàn)繼承(inherited),而不是專有化繼承(即普通的類繼承)。一個(gè)部件可以以'多重繼承'的方式實(shí)現(xiàn)多個(gè)行為的綁定。
行為類必須實(shí)現(xiàn) IBehavior 接口。 大多數(shù)行為可以繼承自 CBehavior 。如果一個(gè)行為需要綁定到一個(gè)模型, 它也可以從專為模型實(shí)現(xiàn)綁定特性的 CModelBehavior 或 CActiveRecordBehavior 繼承。
要使用一個(gè)行為,它必須首先通過調(diào)用此行為的 attach() 方法綁定到一個(gè)組件。然后我們就可以通過組件調(diào)用此行為方法:
// $name 在組件中實(shí)現(xiàn)了對(duì)行為的唯一識(shí)別$component->attachBehavior($name,$behavior);// test() 是行為中的方法。$component->test();
已綁定的行為可以像一個(gè)組件中的普通屬性一樣訪問。例如,如果一個(gè)名為 tree 的行為綁定到了一個(gè)組件,我們就可以通過如下代碼獲得指向此行為的引用。
$behavior=$component->tree;// 等于下行代碼:// $behavior=$component->asa('tree');
行為是可以被臨時(shí)禁止的,此時(shí)它的方法就會(huì)在組件中失效。例如:
$component->disableBehavior($name);// 下面的代碼將拋出一個(gè)異常$component->test();$component->enableBehavior($name);// 現(xiàn)在就可以使用了$component->test();
兩個(gè)同名行為綁定到同一個(gè)組件下是有可能的。在這種情況下,先綁定的行為則擁有優(yōu)先權(quán)。
當(dāng)和 events, 一起使用時(shí),行為會(huì)更加強(qiáng)大。當(dāng)行為被綁定到組件時(shí),行為里的一些方法就可以綁定到組件的一些事件上了。這樣一來,行為就有機(jī)觀察或者改變組件的常規(guī)執(zhí)行流程。
一個(gè)行為的屬性也可以通過綁定到的組件來訪問。這些屬性包含公共成員變量以及通過 getters 和/或 setters 方式設(shè)置的屬性。例如, 若一個(gè)行為有一個(gè) xyz 的屬性,此行為被綁定到組件 $a,然后我們可以使用表達(dá)式 $a->xyz 訪問此行為的屬性。
八、模塊
模塊是一個(gè)獨(dú)立的軟件單元,它包含 模型, 視圖, 控制器 和其他支持的組件。在許多方面上,模塊看起來像一個(gè)應(yīng)用。主要的區(qū)別就是模塊不能單獨(dú)部署,它必須存在于一個(gè)應(yīng)用里。用戶可以像他們?cè)L問普通應(yīng)用的控制器那樣訪問模塊中的控制器。
模塊在一些場(chǎng)景里很有用。對(duì)大型應(yīng)用來說,我們可能需要把它劃分為幾個(gè)模塊,每個(gè)模塊可以單獨(dú)維護(hù)和部署。一些通用的功能,例如用戶管理,評(píng)論管理,可以以模塊的形式開發(fā),這樣他們就可以容易地在以后的項(xiàng)目中被復(fù)用。
1、創(chuàng)建模塊
模塊組織在一個(gè)目錄中,目錄名即為模塊的唯一ID。模塊目錄的結(jié)構(gòu)跟 應(yīng)用基礎(chǔ)目錄 很相似。下面列出了一個(gè) fourm 的模塊的典型的目錄結(jié)構(gòu):
forum/ 模塊文件夾
ForumModule.php 模塊類文件
components/ 包含可復(fù)用的用戶組件
views/ 包含小物件的視圖文件
controllers/ 包含控制器類文件
DefaultController.php 默認(rèn)的控制器類文件
extensions/ 包含第三方擴(kuò)展
models/ 包含模型類文件
views/ 包含控制器視圖和布局文件
layouts/ 包含布局文件
default/ 包含 DefaultController 的視圖文件
index.php 首頁(yè)視圖文件
模塊必須有一個(gè)繼承自 CWebModule 的模塊類。類的名字通過表達(dá)式 ucfirst($id).'Module' 確定, 其中的 $id 代表模塊的 ID (或者說模塊的目錄名字)。模塊類是存儲(chǔ)模塊代碼間可共享信息的中心位置。例如,我們可以使用 CWebModule::params 存儲(chǔ)模塊參數(shù),使用 CWebModule::components 分享模塊級(jí)的應(yīng)用組件。
2、使用模塊
要使用模塊,首先將模塊目錄放在 應(yīng)用基礎(chǔ)目錄的modules文件夾中。然后在應(yīng)用的modules屬性中聲明模塊ID。例如,為了使用上面的forum模塊,我們可以使用如下應(yīng)用配置:
return array(......'modules'=>array('forum',...),......);
模塊也可以在配置時(shí)帶有初始屬性值。做法和配置 應(yīng)用組件 很類似。例如, forum 模塊可以在其模塊類中有一個(gè)名為 postPerPage 的屬性,它可以在 應(yīng)用配置 中配置如下:
return array(......'modules'=>array('forum'=>array('postPerPage'=>20,),),......);
模塊的實(shí)例可通過當(dāng)前活動(dòng)控制器的 module 屬性訪問。在模塊實(shí)例中,我們可以訪問在模塊級(jí)中共享的信息。例如,為訪問上面的 postPerPage 信息,我們可使用如下表達(dá)式:
$postPerPage=Yii::app()->controller->module->postPerPage;// 如如$this引用的是控制器實(shí)例,則可以使用下行語(yǔ)句// $postPerPage=$this->module->postPerPage;
模塊中的控制器動(dòng)作可以通過路由“模塊ID/控制器ID/動(dòng)作ID”或“模塊ID/存放控制器類文件的子目錄名/控制器ID/動(dòng)作ID”訪問。例如,假設(shè)上面的 forum 模塊有一個(gè)名為 PostController 的控制器,我們就可以通過路由 forum/post/create 訪問此控制器中的 create 動(dòng)作。此路由對(duì)應(yīng)的 URL 即 http://www.example.com/index.php?r=forum/post/create。
3、嵌套的模塊
模塊可以無限級(jí)嵌套。這就是說,一個(gè)模塊可以包含另一個(gè)模塊,而這另一個(gè)模塊又可以包含其他模塊。我們稱前者為 父模塊 ,后者為子模塊。子模塊必須定義在其父模塊的 modules 屬性中,就像我們前面在應(yīng)用配置中定義模塊一樣。
要訪問子模塊中的控制器動(dòng)作,我們應(yīng)使用路由 父模塊ID/子模塊ID/控制器ID/動(dòng)作ID。
九、路徑別名
Yii 中廣泛的使用了路徑別名。路徑別名關(guān)聯(lián)于一個(gè)目錄或文件的路徑。它以點(diǎn)號(hào)語(yǔ)法指定,類似于廣泛使用的名字空間(namespace)格式:
RootAlias.path.to.target
其中的 RootAlias 是某個(gè)現(xiàn)存目錄的別名,通過調(diào)用 YiiBase::setPathOfAlias(), 我們可以定義新的路徑別名。為方便起見,Yii 預(yù)定義了以下幾個(gè)根別名:
system: 表示 Yii 框架目錄;
zii: 表示 Zii 庫(kù) 目錄;
application: 表示應(yīng)用的 基礎(chǔ)目錄;
webroot: 表示 入口腳本 文件所在的目錄。
ext: 表示包含了所有第三方 擴(kuò)展 的目錄。
額外的,如果應(yīng)用使用了 模塊, (Yii) 也為每個(gè)模塊ID定義了根別名,指向相應(yīng)模塊的跟目錄。
通過使用 YiiBase::getPathOfAlias(), 別名可以被翻譯為其相應(yīng)的路徑。
使用別名可以很方便的導(dǎo)入類的定義。例如,如果我們想包含 CController 類的定義,我們可以調(diào)用如下代碼
import方法跟 include 和 require 不同,它更加高效。導(dǎo)入(import)的類定義并不會(huì)真正被包含進(jìn)來,直到它第一次被引用。多次導(dǎo)入同樣的名字空間也會(huì)比 include_once 和 require_once 快得多。
我們還可以使用如下語(yǔ)法導(dǎo)入整個(gè)目錄,這樣此目錄下的類文件就會(huì)在需要時(shí)被自動(dòng)包含。
除 import 外, 別名還在其他許多地方指向類。例如,路徑別名可以傳遞給 Yii::createComponent() 以創(chuàng)建相應(yīng)類的實(shí)例。即使類文件在之前從未被包含。
不要將路徑別名和名字空間混淆了,名字空間是指對(duì)一些類名的一個(gè)邏輯組合,這樣它們就可以相互區(qū)分開,即使有相同的名字。而路徑別名是用于指向一個(gè)類文件或目錄。路徑別名與名字空間并不沖突。
十、開發(fā)規(guī)范
下面我們講解 Yii 編程中推薦的開發(fā)規(guī)范。為簡(jiǎn)單起見,我們假設(shè) WebRoot 是 Yii 應(yīng)用安裝的目錄。
1、URL
默認(rèn)情況下,Yii 識(shí)別如下格式的 URL:
http://hostname/index.php?r=ControllerID/ActionID
r 變量意為 路由(route) ,它可以被Yii解析為 控制器和動(dòng)作。如果 ActionID 被省略,控制器將使用默認(rèn)的動(dòng)作(在CController::defaultAction中定義);如果 ControllerID 也被省略(或者 r 變量不存在),應(yīng)用將使用默認(rèn)的控制器(在CWebApplication::defaultController中定義)。
通過 CUrlManager 的幫助,可以創(chuàng)建更加可識(shí)別,更加 SEO 友好的 URL,例如 http://hostname/ControllerID/ActionID.html。
2、代碼
Yii 推薦命名變量、函數(shù)和類時(shí)使用駝峰風(fēng)格,即每個(gè)單詞的首字母大寫并連在一起,中間無空格。變量名和函數(shù)名應(yīng)該使它們的第一個(gè)單詞全部小寫,以使其區(qū)別于類名。對(duì)私有類成員變量來說,我們推薦以下劃線作為其名字前綴(例如: $_actionList)。
一個(gè)針對(duì)控制器類名的特殊規(guī)則是它們必須以單詞 Controller 結(jié)尾。那么控制器ID就是類名的首字母小寫并去掉單詞Controller。例如,PageController類的ID就是 page。這個(gè)規(guī)則使應(yīng)用更加安全。它還使控制器相關(guān)的URL更加簡(jiǎn)單(例如 /index.php?r=page/index 而不是 /index.php?r=PageController/index)。
3、配置
配置是一個(gè)鍵值對(duì)數(shù)組。每個(gè)鍵代表了所配置的對(duì)象中的屬性名,每個(gè)值則為相應(yīng)屬性的初始值。
類中任何可寫的屬性都可以被配置。如果沒有配置,屬性將使用它們的默認(rèn)值。當(dāng)配置一個(gè)屬性時(shí),最好閱讀相應(yīng)文檔以保證初始值正確。
4、文件
命名和使用文件的規(guī)范取決于它們的類型。
類文件應(yīng)以它們包含的公有類命名。例如,CController 類位于 CController.php 文件中。公有類是可以被任何其他類使用的類。每個(gè)類文件應(yīng)包含最多一個(gè)公有類。私有類(只能被一個(gè)公有類使用的類)可以放在使用此類的公有類所在的文件中。
視圖文件應(yīng)以視圖的名字命名。例如, index 視圖位于 index.php 文件中。視圖文件是一個(gè)PHP腳本文件,它包含了用于呈現(xiàn)內(nèi)容的HTML和PHP代碼。
配置文件可以任意命名。配置文件是一個(gè)PHP腳本,它的主要目的是返回一個(gè)體現(xiàn)配置的關(guān)聯(lián)數(shù)組。
5、目錄
Yii 假定了一系列默認(rèn)的目錄用于不同的場(chǎng)合。如果需要,每個(gè)目錄都可以自定義。
WebRoot/protected: 這是 應(yīng)用基礎(chǔ)目錄,是放置所有安全敏感的PHP腳本和數(shù)據(jù)文件的地方。Yii 有一個(gè)默認(rèn)的 application 別名指向此目錄。此目錄及目錄中的文件應(yīng)該保護(hù)起來防止Web用戶訪問。它可以通過 CWebApplication::basePath 自定義。
WebRoot/protected/runtime: 此目錄放置應(yīng)用在運(yùn)行時(shí)產(chǎn)生的私有臨時(shí)文件。此目錄必須對(duì) Web 服務(wù)器進(jìn)程可寫。它可以通過 CApplication::runtimePath自定義。
WebRoot/protected/extensions: 此目錄放置所有第三方擴(kuò)展。它可以通過 CApplication::extensionPath 自定義。
WebRoot/protected/modules: 此目錄放置所有的應(yīng)用 模塊,每個(gè)模塊使用一個(gè)子目錄。
WebRoot/protected/controllers: 此目錄放置所有控制器類文件。它可以通過 CWebApplication::controllerPath 自定義。
WebRoot/protected/views: 此目錄放置所有試圖文件,包含控制器視圖,布局視圖和系統(tǒng)視圖。它可以通過 CWebApplication::viewPath 自定義。
WebRoot/protected/views/ControllerID: 此目錄放置單個(gè)控制器類中使用的視圖文件。此處的 ControllerID 是指控制器的ID 。它可以通過 CController::viewPath 自定義。
WebRoot/protected/views/layouts: 此目錄放置所有布局視圖文件。它可以通過 CWebApplication::layoutPath 自定義。
WebRoot/protected/views/system: 此目錄放置所有系統(tǒng)視圖文件。系統(tǒng)視圖文件是用于顯示異常和錯(cuò)誤的模板。它可以通過CWebApplication::systemViewPath自定義。
WebRoot/assets: 此目錄放置公共資源文件。資源文件是可以被發(fā)布的,可由Web用戶訪問的私有文件。此目錄必須對(duì) Web 服務(wù)器進(jìn)程可寫。它可以通過 CAssetManager::basePath 自定義
WebRoot/themes: 此目錄放置應(yīng)用使用的不同的主題。每個(gè)子目錄即一個(gè)主題,主題的名字即目錄的名字。它可以通過 CThemeManager::basePath 自定義。
6、數(shù)據(jù)庫(kù)
多數(shù)Web 應(yīng)用是由數(shù)據(jù)庫(kù)驅(qū)動(dòng)的。我們推薦在對(duì)表和列命名時(shí)使用如下命名規(guī)范。注意,這些規(guī)范并不是 Yii 所必須的。
㈠數(shù)據(jù)庫(kù)表名和列名都使用小寫命名。
㈡名字中的單詞應(yīng)使用下劃線分割 (例如 product_order)。
㈢對(duì)于表名,你既可以使用單數(shù)也可以使用復(fù)數(shù)。但不要 同時(shí)使用兩者。為簡(jiǎn)單起見,我們推薦使用單數(shù)名字。
㈣表名可以使用一個(gè)通用前綴,例如 tbl_ 。這樣當(dāng)應(yīng)用所使用的表和另一個(gè)應(yīng)用說使用的表共存于同一個(gè)數(shù)據(jù)庫(kù)中時(shí)就特別有用。這兩個(gè)應(yīng)用的表可以通過使用不同的表前綴很容易地區(qū)別開。
Ⅱ、使用表單
在 Yii 中處理表單時(shí),通常需要以下步驟:
1. 創(chuàng)建用于表現(xiàn)所要收集數(shù)據(jù)字段的模型類。
2. 創(chuàng)建一個(gè)控制器動(dòng)作,響應(yīng)表單提交。
3. 在視圖腳本中創(chuàng)建與控制器動(dòng)作相關(guān)的表單。
一、創(chuàng)建模型
在編寫表單所需的 HTML 代碼之前,我們應(yīng)該先確定來自最終用戶輸入的數(shù)據(jù)的類型,以及這些數(shù)據(jù)應(yīng)符合什么樣的規(guī)則。模型類可用于記錄這些信息。正如模型章節(jié)所定義的,模型是保存用戶輸入和驗(yàn)證這些輸入的中心位置。
取決于使用用戶所輸入數(shù)據(jù)的方式,我們可以創(chuàng)建兩種類型的模型。如果用戶輸入被收集、使用然后丟棄,我們應(yīng)該創(chuàng)建一個(gè)表單模型; 如果用戶的輸入被收集后要保存到數(shù)據(jù)庫(kù),我們應(yīng)使用一個(gè)Active Record。兩種類型的模型共享同樣的基類 CModel ,它定義了表單所需的通用接口。
1、定義模型類
例如創(chuàng)建為一個(gè)表單模型:
class LoginForm extends CFormModel{public $username;public $password;public $rememberMe=false;}
LoginForm 中定義了三個(gè)屬性: $username, $password 和 $rememberMe。他們用于保存用戶輸入的用戶名和密碼,還有用戶是否想記住他的登錄的選項(xiàng)。由于 $rememberMe 有一個(gè)默認(rèn)的值 false,相應(yīng)的選項(xiàng)在初始化顯示在登錄表單中時(shí)將是未勾選狀態(tài)。
我們將這些成員變量稱為特性(attributes)而不是屬性(properties),以區(qū)別于普通的屬性(properties)。特性(attribute)是一個(gè)主要用于存儲(chǔ)來自用戶輸入或數(shù)據(jù)庫(kù)數(shù)據(jù)的屬性(propertiy)。
2、聲明驗(yàn)證規(guī)則
一旦用戶提交了他的輸入,模型被填充,我們就需要在使用前確保用戶的輸入是有效的。這是通過將用戶的輸入和一系列規(guī)則執(zhí)行驗(yàn)證實(shí)現(xiàn)的。我們?cè)?rules() 方法中指定這些驗(yàn)證規(guī)則,此方法應(yīng)返回一個(gè)規(guī)則配置數(shù)組。
class LoginForm extends CFormModel{public $username;public $password;public $rememberMe=false;private $_identity;public function rules(){return array(array('username, password', 'required'), //username 和 password 為必填項(xiàng)array('rememberMe', 'boolean'), //rememberMe 應(yīng)該是一個(gè)布爾值array('password', 'authenticate'), //password 應(yīng)被驗(yàn)證(authenticated));}public function authenticate($attribute,$params){$this->_identity=new UserIdentity($this->username,$this->password);if(!$this->_identity->authenticate())$this->addError('password','錯(cuò)誤的用戶名或密碼。');}}
rules() 返回的每個(gè)規(guī)則必須是以下格式:
其中:
AttributeList(特性列表)是需要通過此規(guī)則驗(yàn)證的特性列表字符串,每個(gè)特性名字由逗號(hào)分隔;
Validator(驗(yàn)證器) 指定要執(zhí)行驗(yàn)證的種類;
on 參數(shù)是可選的,它指定此規(guī)則應(yīng)被應(yīng)用到的場(chǎng)景列表;
附加選項(xiàng) 是一個(gè)名值對(duì)數(shù)組,用于初始化相應(yīng)驗(yàn)證器的屬性值。
希望本文所述對(duì)大家基于Yii框架的PHP程序設(shè)計(jì)有所幫助。