初學Yii,剛看到其組件機制,特別是剛看“組件事件”的時候真是把人給看暈了,可能還是基礎不好的吧........接下來做個筆記備忘!!!
Yii的組件機制
組件機制,是Yii整個體系的思想精髓,在使用Yii之前,最應該先了解其組件機制,如果不瞭解這個機制,那麼閱讀Yii源代碼會非常吃力。組件機制給Yii框架賦予了無窮的靈活性和可擴展性,可以毫不誇張地說,Yii框架的基礎結構就是組件。大到CApplication對象、控制器、路由管理器(urlManager),小到一些其它插件,均是以組件形式存在的。
什麼是Yii組件?
Yii中幾乎所有可實例化並繼承自CComponent的類,均可稱爲組件。
組件的特點是什麼?
繼承自CComponent類(直接繼承或間接繼承),擁有事件及行爲機制,可在配置文件中定義其各個屬性。
組件中的“事件”:
一個示例演示 組件事件如何運行。
/*
*一個控制器(Controller)其實也是組件,因爲其最後還是繼承的CComponentl類。
*這個例子也只僅僅演示組件事件將如何運行。
*/
class ComponentTestController extends Controller
{
/*
*這定義一個事件onSubmit
*定義的格式是固定的。函數名稱必須和$this->raiseEvent()的第一個參數名稱一致。
*$event 是一個CEvent或者其子類的實例。 具體看第74行調用代碼。
*/
public function onSubmit($event){
/*這個方法意思是在調用onSubmit這個時間的時候,去觸發執行綁定到這個時間的函數*/
$this->raiseEvent("onSubmit", $event);
}
/**
*這裏的test1~test4都是自定義方法,用於綁定到onSubmit時間中。
*如果 onSubmit觸發並且下面的某些方法被綁定,則被綁定方法會執行。
*/
public function test1(){
echo "這是在促發onSubmit時候執行的函數1<br />";
}
public function test2(){
echo "這是在促發onSubmit時候執行的函數2<br />";
}
public function test3(){
echo "這是在促發onSubmit時候執行的函數3<br />";
}
/*帶參數*/
public function test4($data){
echo "這是在促發onSubmit時候執行的函數4<br />";
echo "<pre>";
print_r($data->params);
echo "</pre>";
}
public function actionIndex(){
/**
****
*有兩種方式對onSuubmit事件進行方法綁定。
*下面綁定了多個方法,綁定方法按照被綁定的順序進行執行。
****
*綁定方法1.$this->onSubmit=$callback;
*綁定方法2.$this->attachEventHandler("onSubmit", $callback);
*$callback代表一個事件處理程序。
* 一個事件處理程序必須是一個有效的PHP回調。
* 如,一個指字全局函數名的字符串或一個數組,該數組包含兩個元素, 第一個元素是一個對象, 第二個元素是這個對象的方法。
*
*/
/*1.綁定方式一:使用setter方法綁定事件。初學者可能會驚訝於onSubmit屬性爲什麼沒定義就可以這樣訪問.....*/
//這裏是綁定當前的test3函數,array裏面的第一個元素是一個$this對象。
//如果綁定的是其他對象的裏面的方法,比如 自定義了一個對象form 裏面有add方法。就應該這麼寫:
//$form=new Form();
//$this->onSubmit=array($form,"add");
$this->onSubmit=array($this,"test3");
$this->onSubmit=array($this,"test1");
$this->onSubmit=array($this,"test2");
/*2.綁定方式二*/
$this->attachEventHandler("onSubmit", array($this,"test4"));
/**
* 觸發(調用)onSubmit事件,這個時候綁定在onSubmit上面的所有方法(test1,test2,test3...)將按順序執行
*
* new CEvent($this,array("name"=>"參數一","sex"=>"參數二"))中的$this表明觸發這個onSubmit事件的對象誰!
* array("name"=>"參數一","sex"=>"參數二") 數組爲傳入到綁定函數中的參數數據
*/
$this->onSubmit(new CEvent($this,array("name"=>"參數一","sex"=>"參數二")));
}
}
運行結果如下:
這是在促發onSubmit時候執行的函數3
這是在促發onSubmit時候執行的函數1
這是在促發onSubmit時候執行的函數2
這是在促發onSubmit時候執行的函數4
Array
(
[name] => 參數一
[sex] => 參數二
)
下面這個是看到別人的文章中對組件事件的使用示例。
- 例如我們希望當表單提交的時候,將此事件通知給日誌組件讓其記錄之
定義一個form組件(是組件就必須直接或者間接的繼承CComponent),並定義一個onSubmit事件(事件名稱自己寫啦...)
class form extends CComponent {
public function onSubmit($event) {
$this->raiseEvent('onSubmit', $event);
}
}
在一段代碼中實例化這個組件,比如在一個action中。
class PostController extends Controller
{
public function actionUser{
//實例化一個上面定義好的from組件。(但首先要把這個組件代碼文件引入進來吧.....0.0)
$form = new form();
$logOjbect =new logOjbect();//實例化一個對象,我們要用到這個對象中的方法。
//方法綁定了。把$logOjbect對象中的saveLog方法綁定到$form對象(專業點叫‘組件’...)中的onSubmit事件中。
$form ->attachEventHandler( 'onSubmit', array($logOjbect, "saveLog") );
//觸發事件並執行其綁定的方法。這裏把POST過來的數據傳遞到$logOjbect對象中的saveLog方法中,由saveLog對數據進行處理.
$form->onSubmit(new CEvent($form, array('data'=>$_POST) ) );
}
}
//logObject代碼
class logObject {
public function saveLog($event) {
//接收數據
$data=$event->params ;
//TODO 對數據的保存操作
}
}
組件中的“行爲”:行爲就是一個特殊的類。
一個行爲的運行示例。
1.先定義一個行爲類。
/*
* 定義一個行爲。
*/
class MyBehavior extends CBehavior {
public $name="行爲中的name屬性<br />";
public function test1(){
echo "行爲中的一個方法Test1<br />";
}
public function test2(){
echo "行爲中的一個方法Test2<br />";
}
public function test3(){
echo "行爲中的一個方法Test3<br />";
}
public function events() {
return array(
'onSubmit' => 'test3', //指定調用此行爲的組件的onSubmit事件發生後,自動調用行爲的test2
);
}
}
2.在一個類中(一個控制器組件或者其他地方,這裏用控制器組件做示例)中使用上面定義的行爲。
Yii::import('application.behavior.MyBehavior');
class BehaviorTestController extends Controller
{
//定義一個事件
public function onSubmit($event){
$this->raiseEvent("onSubmit", $event);
}
public function test1(){
echo "優先執行<br />";
}
public function actionIndex(){
//給組件綁定一個行爲 MyBehavior(當然,這個行爲的類文件也必須先引入進來了...)
$this->attachBehavior('myapp','MyBehavior');
/**
*一旦把行爲幫到到這個組件當中,這個時候就可以使用行爲類當中的所有方法和屬性了。
*和當前組件的對象(這裏是$this)調用自身屬性方法一樣..
*注意:如果當前組件中存在和行爲名稱一樣的方法,將只會執行組件中的方法。
* 如下:$this->test1()只會執行這個控制器組件中的test1方法
*/
echo $this->name;//調用行爲MyBehavior中的name屬性
echo $this->test1();//這裏將執行當前控制器組件的test1,而不是行爲中的test1
echo $this->test2();//調用行爲中的test2方法
//觸發當前組件的onSbumit事件的時候,將會執行行爲中的test3方法。
//因爲這是在行爲類MyBehavior中的events進行了事件綁定
$this->onSubmit(new CEvent($this));
}
}
運行結果如下:
行爲中的name屬性
優先執行
行爲中的一個方法Test2
行爲中的一個方法Test3
一個具有實際應用價值的示例,用以表明什麼時候會用到行爲。
- 我們經常要對用戶輸入的內容進行過濾處理,比如防止其輸入html標籤,這種情況下,我們也可以考慮使用行爲機制處理之
1.先定義一個html過濾行爲類
/**
*定義一個標籤過濾行爲
*
/
class myHtmlFilter extends CBehavior {
public $strip_tags = false ;
//綁定事件。如果綁定了這個行爲的組件觸發了filter事件,將自動運行filterHtml方法
public function events() {
return array(
'filter' => 'filterHtml',
);
}
public function filterHtml($event) {
if($event->sender instanceof CFormModel) {//事件發起者判斷,如果事件是由 CFormModel 對象發起....
$input = $event->sender->attributes ;
$event->sender->attributes = $this->filter($input);
}
}
public function filter(&$data) {
return is_array($data)?array_map(array($this, 'filter'),$data):strip_tags($data);
}
}
2.綁定行爲,使用行爲。
$form = new FormModel;
If($_POST) {
$form->attributes = $_POST ;
//給form組件綁定myHtmlFilter行爲
$form->attachBehavior('myFilter', array(
'class' => 'myHtmlFilter',
'strip_tags' => true ,//給行爲中的$strip_tags屬性賦默認值
));
//觸發$from中的filter事件。這個時候行爲中的filterHtml方法將自動調用
$form->filter(new CEvent($form) ) ;
}
總結:簡單點,事件就是在事件這個方法被觸發的時候可以自動的去執行被綁定好的一個或者一組方法(全局方法或者指定對象中的方法)。行爲就是一個用以完成某種特殊功能的類。在組件(類)中用attachBehavior方法對行爲進行綁定,綁定之後就可以再組件中使用行爲中的所有方法和屬性。