組件機制,是Yii整個體系的思想精髓,在使用Yii之前,最應(yīng)該先了解其組件機制,如果不了解這個機制,那么閱讀Yii源代碼會非常吃力。組件機制給Yii框架賦予了無窮的靈活性和可擴展性,可以毫不夸張地說,Yii框架的基礎(chǔ)結(jié)構(gòu)就是組件。大到Capplication對象、控制器、路由管理器(urlManager),小到一些其它插件,均是以組件形式存在的。
什么是Yii組件?
Yii中幾乎所有可實例化并繼承自CComponent的類,均可稱為組件。
組件的特點是什么?
繼承自CComponent類(直接繼承或間接繼承),擁有事件及行為機制,可在配置文件中定義其各個屬性。
如何創(chuàng)建一個組件?
編寫自定義類,并繼承自CComponent類即可。
CComponent類是所有組件的基類,這個類在Yii框架中至關(guān)重要。具體來說,這個類主要實現(xiàn)以下三大功能:
1.通過利用php的魔術(shù)方法__set,__get實現(xiàn)定義類的屬性。也就是說一個組件的屬性除了使用已經(jīng)定義過的public成員屬性,還可以利用CComponent實現(xiàn)的功能,通過擴展setXXX,getXXX方法擴展屬性的設(shè)置和獲取,對一些特殊的屬性,我們可能希望在設(shè)置它之時就驗證其是格式正確,此時就比較有用。classwebpageextendsCComponent{
public$title;
PRivate$_url;
publicfunctionsetUrl($value=''){
if(is_url($value)){
$this->_url=$value;
}
}
publicfunctiongetUrl(){
return$this->_url;
}
}
$page=newwebpage();
$page->title="pagetitle";
$page->url="/index.php";#call$page->seturl("/index.php");
echo$page->url#$page->geturl();
也就是說,如果一個組件定義了setXXX,getXXX,那么就可以在類外部使用普通的屬性訪問形式。
2.同樣利用setter,getter實現(xiàn)事件處理接口綁定。事件機制在Yii中也是無處不大,Yii使用大量的事件機制來實現(xiàn)組件之間的功能調(diào)用(觀察者模式)。
那么,如何給組件定義一個事件呢?Yii規(guī)定onXX形式的方法,即稱為事件,如以下定義:classformextendsCComponent{
publicfunctiononSubmit($event){
$this->raiseEvent('onSubmit',$event);
}
}
使用以上固定代碼,就給car組件創(chuàng)建了一個onStop事件。但是綁定事件究竟有何用處呢?綁定事件的作用就是當(dāng)組件產(chǎn)生一系列事件時,將自己的事件通過事件處理器,通知到綁定的各個對象上。例如我們希望當(dāng)表單提交的時候,將此事件通知給日志組件讓其記錄之。
$form=newform();
$form->attachEventHandler('onSubmit',array($logOjbect,"saveLog"));
$form->data=$_POST;
$form->onSubmit(newCEvent($form,array('data'=>$_POST)));#激活事件執(zhí)行,并調(diào)用事件處理接口logObject::saveLog
而logObject的代碼可能如下:classlogObject{
publicfunctionsaveLog($event){
$event->sender===$form;
$event->params;
}
}
顯然這種方式遠(yuǎn)比傳統(tǒng)方式調(diào)用更靈活,概念方式上也更先進(jìn)一些。
另外,可以使用setter方法綁定事件:
$form->onSubmit=array($logOjbect,"saveLog");
注意:form類并未定義onSubmit成員屬性。
同時,Yii實現(xiàn)了同一個事件綁定多個處理接口的機制,類似javaScript中的addEventListener。
事件處理器接口柳芽,以php的callback類型格式為標(biāo)準(zhǔn),詳情參閱以下內(nèi)容:http://php.net/manual/en/language.types.callable.php
如Yii的CLogRouter::init()中的代碼:Yii::app()->attachEventHandler('onEndRequest',array($this,'processLogs'));
當(dāng)然也可以寫成Yii::app()->onEndRequest=array($this,'processLogs');
而CApplication中定義了onEndRequest事件:publicfunctiononEndRequest($event){
if(!$this->_ended){
$this->_ended=true;
$this->raiseEvent('onEndRequest',$event);
}
}
定義了事件,并給事件綁定了處理器還不夠,還得在合適的地方激活事件,如CApplication::run()方法中的邏輯:
publicfunctionrun(){
if($this->hasEventHandler('onBeginRequest'))
$this->onBeginRequest(newCEvent($this));
$this->processRequest();
新聞熱點
疑難解答