行為是 [[yii\base\Behavior]] 或其子類的範例。行為,也稱為 mixins,可以無須改變類繼承關係即可增強一個已有的 [[yii\base\Component|元件]] 類功能。當行為附加到元件後,它將“注入”它的方法和屬性到元件,然後可以像存取元件內定義的方法和屬性一樣存取它們。此外,行為通過元件能響應被觸發的事件,從而自定義或調整元件正常執行的程式碼。
要定義行為,通過繼承 [[yii\base\Behavior]] 或其子類來建立一個類。如:
以上程式碼定義了行為類 app\components\MyBehavior
並為要附加行為的元件提供了兩個屬性 prop1
、prop2
和一個方法 foo()
。注意屬性 prop2
是通過 getter getProp2()
和 setter setProp2()
定義的。能這樣用是因為 [[yii\base\Object]] 是 [[yii\base\Behavior]] 的祖先類,此祖先類支援用 getter 和 setter 方法定義屬性
提示:在行為內部可以通過 [[yii\base\Behavior::owner]] 屬性存取行為已附加的元件。
如果要讓行為響應對應元件的事件觸發,就應覆寫 [[yii\base\Behavior::events()]] 方法,如:
[[yii\base\Behavior::events()|events()]] 方法返回事件列表和相應的處理器。上例宣告了 [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] 事件和它的處理器beforeValidate()
。當指定一個事件處理器時,要使用以下格式之一:
處理器的格式如下,其中 $event 指向事件引數。關於事件的更多細節請參考事件:
可以靜態或動態地附加行為到[[yii\base\Component|元件]]。前者在實踐中更常見。
要靜態附加行為,覆寫行為要附加的元件類的 [[yii\base\Component::behaviors()|behaviors()]] 方法即可。[[yii\base\Component::behaviors()|behaviors()]] 方法應該返回行為組態列表。每個行為組態可以是行為類名也可以是組態陣列。如:
通過指定行為組態陣列相應的鍵可以給行為關聯一個名稱。這種行為稱為命名行為。上例中,有兩個命名行為:myBehavior2
和 myBehavior4
。如果行為沒有指定名稱就是匿名行為。
要動態附加行為,在對應元件裡呼叫 [[yii\base\Component::attachBehavior()]] 方法即可,如:
可以通過 [[yii\base\Component::attachBehaviors()]] 方法一次附加多個行為:
還可以通過組態去附加行為:
詳情請參考組態章節。
使用行為,必須像前文描述的一樣先把它附加到 [[yii\base\Component|component]] 類或其子類。一旦行為附加到元件,就可以直接使用它。
行為附加到元件後,可以通過元件存取一個行為的公共成員變數或 getter 和 setter 方法定義的屬性:
類似地也可以呼叫行為的*公共方法:
如你所見,儘管 $component
未定義 prop1
和 bar()
,它們用起來也像元件自己定義的一樣。
如果兩個行為都定義了一樣的屬性或方法,並且它們都附加到同一個元件,那麼首先附加上的行為在屬性或方法被存取時有優先權。
附加行為到元件時的命名行為,可以使用這個名稱來存取行為物件,如下所示:
也能獲取附加到這個元件的所有行為:
要移除行為,可以呼叫 [[yii\base\Component::detachBehavior()]] 方法用行為相關聯的名字實現:
也可以移除全部行為:
TimestampBehavior
最後以 [[yii\behaviors\TimestampBehavior]] 的講解來結尾,這個行為支援在 [[yii\db\ActiveRecord|Active Record]] 儲存時自動更新它的時間戳屬性。
首先,附加這個行為到計劃使用該行為的 [[yii\db\ActiveRecord|Active Record]] 類:
以上指定的行為陣列:
儲存 User 物件,將會發現它的 created_at 和 updated_at 屬性自動填充了當前時間戳:
``php $user = new User; $user->email = '[email protected]'; $user->save(); echo $user->created_at; // 顯示當前時間戳
[[yii\behaviors\TimestampBehavior|TimestampBehavior]] 行為還提供了一個有用的方法 [[yii\behaviors\TimestampBehavior::touch()|touch()]],這個方法能將當前時間戳賦值給指定屬性並儲存到資料庫:
```php
$user->touch('login_time');
儘管行為在 "注入" 屬性和方法到主類方面類似於 traits ,它們在很多方面卻不相同。如上所述,它們各有利弊。它們更像是互補的而不是相互替代。
行為類像普通類支援繼承。另一方面,traits 可以視為 PHP 語言支援的複製貼上功能,它不支援繼承。
行為無須修改元件類就可動態附加到元件或移除。要使用 traits,必須修改使用它的類。
行為是可組態的而 traits 不能。
行為以響應事件來自定義元件的程式碼執行。
當不同行為附加到同一元件產生命名衝突時,這個衝突通過先附加行為的優先權自動解決。而由不同 traits 引發的命名衝突需要通過手工重新命名衝突屬性或方法來解決。
traits 比起行為更高效,因為行為是物件,消耗時間和記憶體。
IDE 對 traits 更友好,因為它們是語言結構。