一、入口文件
入口文件內(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)容:一般格式如下:
<?php
return array(
'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', //當(dāng)前應(yīng)用根目錄的絕對物理路徑
'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ù)器配置
//緩存服務(wù)器1
array('host'=>'server1', 'port'=>11211, 'weight'=>60),
//緩存服務(wù)器2
array('host'=>'server2', 'port'=>11211, 'weight'=>40),
),
),
'db'=>array( //db(數(shù)據(jù)庫)組件配置,“db”為組件ID
'connectionString' => 'sqlite:protected/data/blog.db', //連接數(shù)據(jù)庫的DSN字符串
'tablePrefix' => 'tbl_', //數(shù)據(jù)表前綴
),
// 如果要使用一個(gè)MySQL數(shù)據(jù)庫溜族,請取消下面的注釋
'errorHandler'=>array(
// 使用SiteController控制器類中的actionError方法顯示錯(cuò)誤
//遇到錯(cuò)誤時(shí)煌抒,運(yùn)行的操作寡壮。控制器名和方法名均小寫屋群,并用斜線“/”隔開
'errorAction'=>'site/error',
),
//URL路由管理器
'urlManager'=>array(
//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ī)則:
'urlFormat'=>'path',
'rules'=>array( //URL規(guī)則否纬。語法:<參數(shù)名:正則表達(dá)式>
//將post/12/helloword指向post/view?id=12&title=helloword
'post/<id:\d+>/<title:.*?>'=>'post/view',
//將posts/hahahaha指向post/index?tag=hahahaha
'posts/<tag:.*?>'=>'post/index',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
),
'log'=>array( //記錄
'class'=>'CLogRouter', //處理記錄信息的類
'routes'=>array(
array(
'class'=>'CFileLogRoute', //處理錯(cuò)誤信息的類
'levels'=>'error, warning', //錯(cuò)誤等級
),
// 如要將錯(cuò)誤記錄消息在網(wǎng)頁上顯示临燃,取消下面的注釋即可
),
),
), //應(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 組件用于解析用戶請求并提供例如 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ù)庫連接巫俺。注意介汹,使用此組件你必須配置其 connectionString 屬性。
errorHandler: CErrorHandler - 處理未捕獲的 PHP 錯(cuò)誤和異常稽穆。
format: CFormatter - 格式化數(shù)值顯示赶撰。此功能從版本 1.1.0 起開始提供豪娜。
messages: CPhpMessageSource - 提供Yii應(yīng)用中使用的信息翻譯。
request: CHttpRequest - 提供關(guān)于用戶請求的信息否灾。
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)前用戶的識別信息茅主。
themeManager: CThemeManager - 管理主題。
要訪問一個(gè)應(yīng)用組件响牛,使用 Yii::app()->組件的ID
三娃善、控制器(Controller)
控制器 是 CController 類的子類的實(shí)例瑞佩。它在當(dāng)用戶請求時(shí)由應(yīng)用創(chuàng)建。當(dāng)一個(gè)控制器運(yùn)行時(shí)瘫寝,它執(zhí)行所請求的動(dòng)作(控制器類方法)焕阿,動(dòng)作通常會引入所必要的模型并渲染相應(yīng)的視圖首启。動(dòng)作,就是一個(gè)名字以 action 開頭的控制器類方法(action+大寫首字母的動(dòng)作名)褒纲。
控制器類文件保存位置protected/controllers/控制器和動(dòng)作以 ID 識別莺掠。
控制器ID 是一種 '父目錄/子目錄/控制器名' 的格式读宙,對應(yīng)相應(yīng)的控制器類文件 protected/controllers/父目錄/子目錄/大寫首字母的控制器名Controller.php;
動(dòng)作ID 是除去 action 前綴的動(dòng)作方法名唇兑。
1扎附、路由
用戶以路由的形式請求特定的控制器和動(dòng)作察纯。路由是由控制器 ID 和動(dòng)作 ID 連接起來的,兩者以斜線分割香伴。
例如即纲,路由 post/edit 代表 PostController 及其 edit 動(dòng)作博肋。默認(rèn)情況下,URL http://hostname/index.php?r=post/edit 即請求此控制器和動(dòng)作膊畴。
注意: 默認(rèn)情況下唇跨,路由是大小寫敏感的衬衬。可以通過設(shè)置應(yīng)用配置中的 CUrlManager::caseSensitive 為 false 使路由對大小寫不敏感玉控。當(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ī)則確定控制器的類以及類文件的位置:
1贡歧、如果指定了 CWebApplication::catchAllRequest , 控制器將基于此屬性創(chuàng)建赋秀,而用戶指定的控制器 ID 將被忽略猎莲。這通常用于將應(yīng)用設(shè)置為維護(hù)狀態(tài)并顯示一個(gè)靜態(tài)提示頁面技即。
2而叼、如果在 CWebApplication::controllerMap 中找到了 ID, 相應(yīng)的控制器配置將被用于創(chuàng)建控制器實(shí)例。
3液荸、如果 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 單詞作為前綴命名的方法慷垮。而更高級的方式是定義一個(gè)動(dò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(
//使用“應(yīng)用程序文件夾/controllers/post/UpdateAction.php”文件中的類來處理edit動(dòng)作
'edit'=>'application.controllers.post.UpdateAction',
);
}
}
如上所示傲宜,我們使用了路徑別名“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
四玄坦、過濾器(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í)例宣脉,代表與所請求動(dòng)作相關(guān)的過濾器列表塑猖。在過濾器方法中羊苟,我們可以調(diào)用 $filterChain->run() 以繼續(xù)執(zhí)行后續(xù)過濾器和動(dòng)作感憾。
如 動(dòng)作 一樣,過濾器也可以是一個(gè)對象巍虫,它是 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)用的邏輯
}
}
要對動(dòng)作應(yīng)用過濾器瓦胎,我們需要覆蓋 CController::filters() 方法尤揣。此方法應(yīng)返回一個(gè)過濾器配置數(shù)組。例如:
class PostController extends CController
{
......
public function filters()
{
return array(
//將postOnly過濾器應(yīng)用于edit和create動(dòng)作(這是基于方法的過濾器)
'postOnly + edit, create',
array( //使用了數(shù)組來配置過濾器
//將application.filters.PerformanceFilter過濾器應(yīng)用于除了edit和create之外的所有動(dòng)作(這是基于對象的過濾器)
'application.filters.PerformanceFilter - edit, create',
'unit'=>'second', //初始化過濾器對象中的unit屬性值為second
),
);
}
}
上述代碼指定了兩個(gè)過濾器: postOnly 和 PerformanceFilter负芋。 postOnly 過濾器是基于方法的(相應(yīng)的過濾器方法已在 CController 中定義)旧蛾;而 performanceFilter 過濾器是基于對象的。路徑別名 application.filters.PerformanceFilter 指定過濾器類文件是 protected/filters/PerformanceFilter毯盈。我們使用一個(gè)數(shù)組配置 PerformanceFilter 病袄,這樣它就可被用于初始化過濾器對象的屬性值。此處 PerformanceFilter 的 unit 屬性值將被初始為 second脑奠。
使用加減號捺信,我們可指定哪些動(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)作菩咨。如果過濾器配置中沒有使用加減號抽米,則此過濾器將被應(yīng)用于所有動(dòng)作糙置。
五、模型(Model)
模型是 CModel 或其子類的實(shí)例标捺。模型用于保持?jǐn)?shù)據(jù)以及與其相關(guān)的業(yè)務(wù)邏輯亡容。
模型是單獨(dú)的數(shù)據(jù)對象冤今。它可以是數(shù)據(jù)表中的一行,或者一個(gè)用戶輸入的表單屋谭。
數(shù)據(jù)對象的每個(gè)字段對應(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è)登錄頁面中,我們可以使用表單模型用于表示由最終用戶提供的用戶名和密碼信息军熏。
Active Record (AR) 是一種用于通過面向?qū)ο蟮娘L(fēng)格抽象化數(shù)據(jù)庫訪問的設(shè)計(jì)模式刃唐。每個(gè) AR 對象是一個(gè) CActiveRecord 或其子類的實(shí)例画饥。代表數(shù)據(jù)表中的一行。行中的字段對應(yīng) AR 對象中的屬性热鞍。
六、視圖
視圖是一個(gè)包含了主要的用戶交互元素的PHP腳本.
視圖有一個(gè)名字偷办,當(dāng)渲染(render)時(shí)椒涯,名字會被用于識別視圖腳本文件回梧。視圖的名稱與其視圖腳本名稱是一樣的。例如:視圖 edit 的名稱出自一個(gè)名為 edit.php 的腳本文件湖苞。要渲染時(shí)详囤,需通過傳遞視圖的名稱調(diào)用 CController::render()。這個(gè)方法將在“protected/views/控制器ID”目錄下尋找對應(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 則儲存了內(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ù)組']); ?>
...可能會由小物件獲取的內(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ù)組的值則是小物件屬性所對應(yīng)的值。如下所示 :
<?php
$this->widget('CMaskedTextField',array(
'mask'=>'99/99/9999'
));
?>
繼承 CWidget 并覆蓋其init()和run()方法,可以定義一個(gè)新的小物件:
class MyWidget extends CWidget
{
public function init()
{
// 此方法會被 CController::beginWidget() 調(diào)用
}
public function run()
{
// 此方法會被 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ò)誤號XXX的 CHttpException 的視圖虑椎。例如,如果 CHttpException 拋出一個(gè)404錯(cuò)誤,那么 error404 就會被顯示捆姜。
在 framework/views 下, Yii 提供了一系列默認(rèn)的系統(tǒng)視圖. 他們可以通過在 protected/views/system 下創(chuàng)建同名視圖文件進(jìn)行自定義迎膜。
七、組件
Yii 應(yīng)用建立于組件之上珊豹。組件是 CComponent 或其子類的實(shí)例宽涌。使用組件主要涉及訪問它的屬性以及觸發(fā)或處理它的時(shí)間卸亮〖婷常基類 CComponent 指定了如何定義屬性和事件吃溅。
1、組件屬性
組件的屬性就像對象的公共成員變量螺垢。它是可讀寫的。
要定義一個(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() 就會被調(diào)用隙袁,其返回值則成為屬性值弃榨;相似的,當(dāng)寫入屬性時(shí)娜饵,setTextWidth() 被調(diào)用箱舞。如果 setter 方法沒有定義拳亿,則屬性將是只讀的,如果對其寫入則會拋出一個(gè)異常电湘。使用 getter 和 setter 方法定義一個(gè)屬性有一個(gè)好處:即當(dāng)讀取或?qū)懭雽傩詴r(shí)寂呛,可以執(zhí)行額外的邏輯(例如瘾晃,執(zhí)行驗(yàn)證,觸發(fā)事件)劫拢。
注意: 通過 getter/setter 定義的屬性和類成員變量之間有一個(gè)細(xì)微的差異:屬性的名字是大小寫不敏感的, 而 類成員變量是大小寫敏感的妹沙。
2狗唉、組件事件
組件事件是一些特殊的屬性,它們使用一些稱作 事件句柄(event handlers)的方法作為其值肾筐。分配一個(gè)方法到一個(gè)事件將會引起方法在事件被喚起處自動(dòng)被調(diào)用吗铐。因此杏节,一個(gè)組件的行為可能會被一種在部件開發(fā)過程中不可預(yù)見的方式修改。
組件事件以 on 開頭的命名方式定義镊逝。和屬性通過 getter/setter 方法來定義的命名方式一樣嫉鲸,事件的名稱是大小寫不敏感的。以下代碼定義了一個(gè) onClicked 事件:
public function onClicked($event)
{
$this->raiseEvent('onClicked', $event);
}
這里作為事件參數(shù)的 $event 是 CEvent 或其子類的實(shí)例座菠。
我們可以分配一個(gè)方法到此事件浴滴,如下所示:
$component->onClicked=$callback;
這里的 $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)于誰觸發(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í)行瑞侮,它會設(shè)置 $event->handled 為 true。
3越妈、組件行為
組件已添加了對 mixin 的支持钮糖,并可以綁定一個(gè)或多個(gè)行為店归。行為是一個(gè)對象,其方法可以被它綁定的部件通過收集功能的方式來實(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)了對行為的唯一識別
$component->attachBehavior($name,$behavior);
// test() 是行為中的方法轨淌。
$component->test();
已綁定的行為可以像一個(gè)組件中的普通屬性一樣訪問递鹉。例如,如果一個(gè)名為 tree 的行為綁定到了一個(gè)組件却盘,我們就可以通過如下代碼獲得指向此行為的引用媳拴。
$behavior=$component->tree;
// 等于下行代碼:
// $behavior=$component->asa('tree');
行為是可以被臨時(shí)禁止的,此時(shí)它的方法就會在組件中失效。例如:
$component->disableBehavior($name);
// 下面的代碼將拋出一個(gè)異常
$component->test();
$component->enableBehavior($name);
// 現(xiàn)在就可以使用了
$component->test();
兩個(gè)同名行為綁定到同一個(gè)組件下是有可能的塞关。在這種情況下,先綁定的行為則擁有優(yōu)先權(quán)帆赢。
當(dāng)和 events, 一起使用時(shí),行為會更加強(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)用里。用戶可以像他們訪問普通應(yīng)用的控制器那樣訪問模塊中的控制器粥惧。
模塊在一些場景里很有用陪每。對大型應(yīng)用來說,我們可能需要把它劃分為幾個(gè)模塊挂签,每個(gè)模塊可以單獨(dú)維護(hù)和部署饵婆。一些通用的功能戏售,例如用戶管理草穆,評論管理悲柱,可以以模塊的形式開發(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 首頁視圖文件
模塊必須有一個(gè)繼承自 CWebModule 的模塊類吨瞎。類的名字通過表達(dá)式 ucfirst($id).'Module' 確定, 其中的 $id 代表模塊的 ID (或者說模塊的目錄名字)颤诀。模塊類是存儲模塊代碼間可共享信息的中心位置对湃。例如,我們可以使用 CWebModule::params
存儲模塊參數(shù)心傀,使用 CWebModule::components
分享模塊級的應(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í)例中坛增,我們可以訪問在模塊級中共享的信息收捣。例如庵楷,為訪問上面的 postPerPage 信息,我們可使用如下表達(dá)式:
$postPerPage=Yii::app()->controller->module->postPerPage;
// 如如$this引用的是控制器實(shí)例咐蚯,則可以使用下行語句
// $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)作呐萌。此路由對應(yīng)的 URL 即 http://www.example.com/index.php?r=forum/post/create脚线。
3、嵌套的模塊
模塊可以無限級嵌套渠旁。這就是說,一個(gè)模塊可以包含另一個(gè)模塊粤铭,而這另一個(gè)模塊又可以包含其他模塊杂靶。我們稱前者為 父模塊 吗垮,后者為子模塊。子模塊必須定義在其父模塊的 modules 屬性中怯屉,就像我們前面在應(yīng)用配置中定義模塊一樣饵沧。
要訪問子模塊中的控制器動(dòng)作,我們應(yīng)使用路由 父模塊ID/子模塊ID/控制器ID/動(dòng)作ID羡儿。
九是钥、路徑別名
Yii 中廣泛的使用了路徑別名咏瑟。路徑別名關(guān)聯(lián)于一個(gè)目錄或文件的路徑。它以點(diǎn)號語法指定兄旬,類似于廣泛使用的名字空間(namespace)格式:
RootAlias.path.to.target
其中的 RootAlias 是某個(gè)現(xiàn)存目錄的別名余寥,通過調(diào)用 YiiBase::setPathOfAlias(), 我們可以定義新的路徑別名。為方便起見绪撵,Yii 預(yù)定義了以下幾個(gè)根別名:
system: 表示 Yii 框架目錄祝蝠;
zii: 表示 Zii 庫 目錄幻碱;
application: 表示應(yīng)用的 基礎(chǔ)目錄细溅;
webroot: 表示 入口腳本 文件所在的目錄。
ext: 表示包含了所有第三方 擴(kuò)展 的目錄恍风。
額外的誓篱,如果應(yīng)用使用了 模塊, (Yii) 也為每個(gè)模塊ID定義了根別名,指向相應(yīng)模塊的跟目錄锦募。
通過使用 YiiBase::getPathOfAlias()
, 別名可以被翻譯為其相應(yīng)的路徑啊研。
使用別名可以很方便的導(dǎo)入類的定義党远。例如沟娱,如果我們想包含 CController 類的定義腕柜,我們可以調(diào)用如下代碼
Yii::import('system.web.CController');
import方法跟 include 和 require 不同,它更加高效砰蠢。導(dǎo)入(import)的類定義并不會真正被包含進(jìn)來唉铜,直到它第一次被引用。多次導(dǎo)入同樣的名字空間也會比 include_once 和 require_once 快得多竞惋。
我們還可以使用如下語法導(dǎo)入整個(gè)目錄拆宛,這樣此目錄下的類文件就會在需要時(shí)被自動(dòng)包含讼撒。
Yii::import('system.web.*');
除 import 外股耽, 別名還在其他許多地方指向類物蝙。例如贡这,路徑別名可以傳遞給 Yii::createComponent()
以創(chuàng)建相應(yīng)類的實(shí)例。即使類文件在之前從未被包含丽惭。
不要將路徑別名和名字空間混淆了辈双,名字空間是指對一些類名的一個(gè)邏輯組合湃望,這樣它們就可以相互區(qū)分開,即使有相同的名字瞳浦。而路徑別名是用于指向一個(gè)類文件或目錄废士。路徑別名與名字空間并不沖突。
十矗蕊、開發(fā)規(guī)范
下面我們講解 Yii 編程中推薦的開發(fā)規(guī)范氢架。為簡單起見,我們假設(shè) WebRoot 是 Yii 應(yīng)用安裝的目錄卿操。
1硬纤、URL
默認(rèn)情況下赃磨,Yii 識別如下格式的 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)建更加可識別拘鞋,更加 SEO 友好的 URL,例如 http://hostname/ControllerID/ActionID.html灰蛙。
2隔躲、代碼
Yii 推薦命名變量、函數(shù)和類時(shí)使用駝峰風(fēng)格障本,即每個(gè)單詞的首字母大寫并連在一起响鹃,中間無空格买置。變量名和函數(shù)名應(yīng)該使它們的第一個(gè)單詞全部小寫强霎,以使其區(qū)別于類名城舞。對私有類成員變量來說,我們推薦以下劃線作為其名字前綴(例如: $_actionList)脱柱。
一個(gè)針對控制器類名的特殊規(guī)則是它們必須以單詞 Controller 結(jié)尾拉馋。那么控制器ID就是類名的首字母小寫并去掉單詞Controller惨好。例如日川,PageController類的ID就是 page矩乐。這個(gè)規(guī)則使應(yīng)用更加安全。它還使控制器相關(guān)的URL更加簡單(例如/index.php?r=page/index
而不是/index.php?r=PageController/index)
分歇。
3卿樱、配置
配置是一個(gè)鍵值對數(shù)組硫椰。每個(gè)鍵代表了所配置的對象中的屬性名,每個(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)的目錄用于不同的場合。如果需要随闽,每個(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í)文件栅炒。
此目錄必須對 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用戶訪問的私有文件王滤。
此目錄必須對 Web 服務(wù)器進(jìn)程可寫滓鸠。它可以通過 CAssetManager::basePath 自定義
WebRoot/themes: 此目錄放置應(yīng)用使用的不同的主題。每個(gè)子目錄即一個(gè)主題踱稍,主題的名字即目錄的名字悠抹。
它可以通過 CThemeManager::basePath 自定義。
6啤挎、數(shù)據(jù)庫
多數(shù)Web 應(yīng)用是由數(shù)據(jù)庫驅(qū)動(dòng)的卵凑。我們推薦在對表和列命名時(shí)使用如下命名規(guī)范。注意掏觉,這些規(guī)范并不是 Yii 所必須的值漫。
㈠數(shù)據(jù)庫表名和列名都使用小寫命名杨何。
㈡名字中的單詞應(yīng)使用下劃線分割 (例如 product_order)。
㈢對于表名危虱,你既可以使用單數(shù)也可以使用復(fù)數(shù)。但不要 同時(shí)使用兩者埃跷。為簡單起見弥雹,我們推薦使用單數(shù)名字。
㈣表名可以使用一個(gè)通用前綴贸诚,例如 tbl_ 。這樣當(dāng)應(yīng)用所使用的表和另一個(gè)應(yīng)用說使用的表共存于同一個(gè)數(shù)據(jù)庫中時(shí)就特別有用酱固。這兩個(gè)應(yīng)用的表可以通過使用不同的表前綴很容易地區(qū)別開运悲。