Yii擴展

1.1 擴展Yii

擴展Yii在開發過程中是很常見的。例如,當你編寫一個新的控制器,你從Yii繼承CController類;當你寫一個新的小工具widget,你繼承於CWidget或者是另外的一個widget。我們這些擴展代碼可以被第三方使用,我們稱之爲yii的擴展。

一個擴展一般只提供單一功能。在Yii裏,可以分爲以下幾類:

●應用組件 application component
●行爲          behavior
●小工具      widget
●控制器      controller
●動作          action
●過濾器      filter
●控制命令 console command
●驗證器      validator
●幫助類      helper
●模塊          module

擴展也可以是一個組件,不屬於以上的分類。實際上,yii非常小心的設計每段代碼,讓每個人可以自己擴展或者是自定義組件。

1.2 使用擴展

使用一個擴展包括以下幾個步驟:

1、從官網地址http://www.yiiframework.com/extensions/ 下載要使用的擴展。

2、在項目的子目錄extensions/xyz下,解壓該擴展。(xyz代表擴展的名稱)

3、導入,配置擴展,然後就可以調用了。

每個擴展都有一個唯一的名稱。假設我們要用的擴展名稱爲xyz,那麼我們一直都可以用路徑別名ext.xyz來訪問擴展的目錄。該目錄下包含了該擴展的所有文件。

不同的擴展有不同的導入要求,配置,以及使用方法。下面,我們按照之前的分類,總結一些常見的擴展使用場景。

1.2.1 Zii擴展

在我們開始介紹使用第三方擴展之前,我們想先介紹以下Zii這個擴展。這個擴展是Yii開發小組開發的,在每個yii的髮型版本中都自帶有的。

當要使用Zii擴展時,你必須在當前類中調用路徑別名zii.path.to.ClassName。這裏的跟目錄別名zii是在Yii裏已經預先定義好的,他指向Zii庫的根目錄。例如,要使用CGridView,我們就在視圖腳本語句中調用以下語句:

  1. $this->widget('zii.widgets.grid.CGridView'array(  
  2. 'dataProvider'=>$dataProvider,  
  3. )); 

1.2.2 應用組件

要使用一個應用組件,我們要在項目的配置文件中的components字段中,加入一個新的選項,如下:

  1. return array(  
  2.     // 'preload'=>array('xyz',...),  
  3.     'components'=>array(  
  4.         'xyz'=>array(  
  5.             'class'=>'ext.xyz.XyzClass',  
  6.             'property1'=>'value1',  
  7.             'property2'=>'value2',  
  8.         ),  
  9.     // other component configurations  
  10.     ),  
  11. ); 

然後,我們就可以在任何地方調用Yii::app()->xyz。組件會滯後創建(也就是,在第一次訪問的時候再生成),除非,我們在預裝載的屬性列表中指定該組件的裝載屬性。

1.2.3 行爲

行爲可以被用於任何類型的組件。他的使用包括2個步驟。第一步,一個行爲要綁定到一個指定的組件。第二步,通過這個目標組件來調用這個行爲。例如:

  1. // $name uniquely identifies the behavior in the component  
  2. $component->attachBehavior($name,$behavior);  
  3. // test() is a method of $behavior  
  4. $component->test(); 

更多情況下,我們是通過配置的方式來綁定一個行爲到目標組件上,而不是調用attachBehavior的方法。例如,要綁定一個行爲到應用組件中,我們可以配置項目工程如下:

  1. return array(  
  2.     'components'=>array(  
  3.         'db'=>array(  
  4.             'class'=>'CDbConnection',  
  5.             'behaviors'=>array(  
  6.                 'xyz'=>array(  
  7.                     'class'=>'ext.xyz.XyzBehavior',  
  8.                     'property1'=>'value1',  
  9.                     'property2'=>'value2',  
  10.                 ),  
  11.             ),  
  12.         ),  
  13.     //....  
  14.     ),  
  15. ); 

上面的代碼中,把xyz的行爲綁定到了一個數據庫組件中。我們之所以可以這麼做,是因爲CApplicationComponent定義了一個叫做behaviors的屬性。通過設置這個屬性爲一個行爲配置列表,當這個組件初始化的時候,會綁定這些行爲。

對於CController, CFormModel 和 CActiveRecord這些經常被用於擴展的類,可以通過重載他們的behaviors的方法來綁定。這些類會在初始化的時候,自動加載這個方法裏的所有行爲:

  1. public function behaviors()  
  2. {  
  3.     return array(  
  4.         'xyz'=>array(  
  5.             'class'=>'ext.xyz.XyzBehavior',  
  6.             'property1'=>'value1',  
  7.             'property2'=>'value2',  
  8.         ),  
  9.     );  

1.2.4 小工具Widget

widget一般用於視圖。假設一個widget類XyzClass屬於xyz擴展,我們可以在視圖中這樣使用:

  1. // widget that does not need body content  
  2. <?php $this->widget('ext.xyz.XyzClass'array(  
  3.     'property1'=>'value1',  
  4.     'property2'=>'value2')); ?>  
  5. // widget that can contain body content  
  6. <?php $this->beginWidget('ext.xyz.XyzClass'array(  
  7.     'property1'=>'value1',  
  8.    'property2'=>'value2')); ?>  
  9.     ...body content of the widget...  
  10. <?php $this->endWidget(); ?> 

1.2.5 動作

動作是一個控制器用來相應特定的用戶請求的。假設一個動作類XyzClass屬於xyz這個擴展,我們可以在控制器中重載CController::actions的方法來使用:

  1. class TestController extends CController  
  2. {  
  3.     public function actions()  
  4.     {  
  5.         return array(  
  6.             'xyz'=>array(  
  7.                 'class'=>'ext.xyz.XyzClass',  
  8.                 'property1'=>'value1',  
  9.                 'property2'=>'value2',  
  10.             ),  
  11.         // other actions  
  12.         );  
  13.     }  

這樣,這個動作就可以就可以通過路由test/xyz來訪問了。

1.2.6 過濾器

過濾器跟動作一樣,也是用於控制器的。他們一般是在一個動作捕獲到用戶時,預先處理,或者是最後處理。假設一個過濾器類XyzClass屬於xyz擴展,我們可以通過重載CController::filters的方法來使用:

  1. class TestController extends CController  
  2. {  
  3.     public function filters()  
  4.     {  
  5.         return array(  
  6.             array(  
  7.                 'ext.xyz.XyzClass',  
  8.                 'property1'=>'value1',  
  9.                 'property2'=>'value2',  
  10.             ),          
  11.             // other filters  
  12.         );  
  13.     }  

在上例中,我們可以在第一個元素組中,用+號或者是減號來限制過濾器只作用於哪些指定的動作。更多詳情請參見控制器說明。

1.2.7 控制器

一個控制器提供了一些能被用戶請求的動作。要用控制器擴展,我們要在項目的配置文件中配置CWebApplication::controllerMap:

  1. return array(  
  2.     'controllerMap'=>array(  
  3.         'xyz'=>array(  
  4.             'class'=>'ext.xyz.XyzClass',  
  5.             'property1'=>'value1',  
  6.             'property2'=>'value2',  
  7.         ),  
  8.         // other controllers  
  9.     ),  
  10. ); 

這樣,控制器中的方法a,我們就可以通過路由xyz/a來訪問了。

1.2.8 校驗器

一個校驗器主要用於模型類(不管是繼承於CFormModel 或CActiveRecord的都可以)。假設一個校驗器類XyzClass屬於擴展xyz的,我們可以在模型類中重載CModel::rules():

  1. class MyModel extends CActiveRecord // or CFormModel  
  2. {  
  3.     public function rules()  
  4.     {  
  5.         return array(  
  6.             array(  
  7.                 'attr1, attr2',  
  8.                 'ext.xyz.XyzClass',  
  9.                 'property1'=>'value1',  
  10.                 'property2'=>'value2',  
  11.             ),  
  12.             // other validation rules  
  13.         );  
  14.     }  

1.2.9 控制檯命令

一個控制檯命令擴展一般用於加強yiic功能。假設一個控制檯命令類屬於xyz擴展,我們可以爲該控制檯配置如下:

  1. return array(  
  2.     'commandMap'=>array(  
  3.         'xyz'=>array(  
  4.             'class'=>'ext.xyz.XyzClass',  
  5.             'property1'=>'value1',  
  6.             'property2'=>'value2',  
  7.         ),  
  8.         // other commands  
  9.     ),  
  10. ); 

然後,我們就能使用配備了額外命令 xyzyiic 工具了。

注意:一個控制檯程序的配置文件使用方法,一般跟web工程的是不同的。如果工程是通過yiic webapp命令創建的,那麼控制檯配置文件就是protected/config/console.php,web工程的配置文件是protected/config/main.php。

1.2.10 模塊

參考模塊的使用說明

1.2.11 通用組件

要使用一個通用組件, 我們首先要導入他的類:

  1. Yii::import('application.extensions.xyz.XyzClass'); 

然後我們可以創建這個類的實例,配置屬性,然後調用他的方法。我們也可以用他創建子類。

1.3 新建擴展

由於擴展是要提供給第三方開發者使用,所以在創建的時候需要額外的工作。以下是一些常規指引:

●擴展最好是隻關自身的。也就是,擴展最好不要對外有關聯。如果說一個擴展,需要另外的安裝包,類,或者是資源,對於開發者來說會很頭疼。
●擴展有關的文件都必須放在以該擴展命名的目錄下
●類名必須有自己的前綴,避免跟其他擴展的類重名。
●擴展必須有完整的安裝說明以及API說明。這樣其他開發者在使用的時候就可以節約很多時間。
●一個擴展要有一個合適的許可。如果你想你的擴展應用於開源或者是閉源項目,你可以使用諸如BSD,MIT等許可。GPL只許可用於開源項目。

接下來,我們來看看如何創建一個擴展。之前關於擴展的描述,同樣適用於你自己的工程。

1.3.1 應用組件

一個應用組件應該實現接口{IApplicationComponent}或者是繼承於IApplicationComponent。主要要實現的方法是IApplicationComponent::init,這個方法裏,組件主要完成初始化工作。這個方法在組件創建以後被調用。

默認情況下,應用組件只有在第一次被請求使用的時候纔會創建。如果想要一個應用組件在項目運行後就創建,那麼必須在CApplication::preload 的屬性中列出。

1.3.2 行爲

要創建一個行爲,必須實現[IBehavior]的接口。爲了簡便,Yii提供了一個基類CBehavior,他已經實現了這個接口,另外還提供了一些簡便的方法。子類主要實現他所想要實現的額外方法。

當爲CModel 和CActiveRecord開發行爲的是時候,也可以繼承於CModelBehavior and CActiveRecordBehavior。這些基類提供了額外的元件,專門爲CModel 和CActiveRecord定做的。例如,CActiveRecordBehavior類實現了一組方法,用來相應ActiveRecord對象的生命週期。子類可以重載這些方法,自定義那些AR生命週期中的代碼。

下面的例子中演示了AR行爲。當這個行爲綁定到一個AR對象中,當AR對象調用save方法時,會自動用當前時間設定create_time 和update_time的屬性值。

  1. class TimestampBehavior extends CActiveRecordBehavior  
  2. {  
  3.     public function beforeSave($event)  
  4.     {  
  5.         if($this->owner->isNewRecord)  
  6.             $this->owner->create time=time();  
  7.         else 
  8.             $this->owner->update time=time();  
  9.     }  

1.3.3 小工具

一個widget可以繼承於CWidget或者是他的子類。

一個創建小工具的最簡單的方法,就是繼承於現有的小工具,重寫他的方法或者是設置他的屬性。例如,你要給CTableView用一個更好的css樣式,你可以在使用小工具的時候,設置他的CTabView::cssFile屬性。你也可以繼承於CTableView,這樣在使用這個widget時就不要配置他的屬性了:

  1. class MyTabView extends CTabView  
  2. {  
  3.     public function init()  
  4.     {  
  5.         if($this->cssFile===null)  
  6.         {  
  7.             $file=dirname(__FILE__).DIRECTORY SEPARATOR.'tabview.css';  
  8.             $this->cssFile=Yii::app()->getAssetManager()->publish($file);  
  9.         }  
  10.     parent::init();  
  11.     }  

上例中,我們重載了CWidget::init方法,然後如果是沒有指定cssFile的屬性,我們就指定爲特定的文件。由於css文件是web不能直接訪問的,所以我們必須作爲一個asset來發布。

咳,精力實在不足了,先暫停到此。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章