Behavior 是 Yii 實現橫向功能復用的核心機制。本文系統梳理 Behavior 的定義規範、三種綁定方式(靜態/動態/配置)、內部綁定流程源碼分析,以及命名與匿名行為的差異。
繼承 yii\base\Behavior,定義公共屬性(含 getter/setter)與方法:
namespace app\components;
use yii\base\Behavior;
class MyBehavior extends Behavior {
public $prop1;
private $_prop2;
public function getProp2() { return $this->_prop2; }
public function setProp2($value) { $this->_prop2 = $value; }
public function foo() { /* ... */ }
}
關鍵點:
yii\base\Object 基礎)$this->owner 存取已綁定的元件對象在元件類中覆寫 behaviors() 回傳行為配置陣列:
namespace app\models;
use yii\db\ActiveRecord;
use app\components\MyBehavior;
class User extends ActiveRecord {
public function behaviors() {
return [
// 匿名行為:僅類名
MyBehavior::className(),
// 命名行為:鍵值對
'myBehavior2' => MyBehavior::className(),
// 匿名行為:配置陣列(可注入屬性初值)
[
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop3' => 'value3',
],
// 命名行為:配置陣列
'myBehavior4' => [
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop3' => 'value3',
],
];
}
}
在應用配置或元件配置中使用 as 前綴:
[
'as myBehavior2' => MyBehavior::className(),
'as myBehavior3' => [
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop3' => 'value3',
],
]
// 單個綁定
$component->attachBehavior('myBehavior1', new MyBehavior());
// 批次綁定
$component->attachBehaviors([
'myBehavior1' => new MyBehavior(), // 命名
MyBehavior::className(), // 匿名
]);
| 類型 | 特徵 | 可透過 getBehavior() 取得 | 可精確移除 |
|---|---|---|---|
| 命名行為 | 綁定時指定鍵名 | 是 | 是 |
| 匿名行為 | 無鍵名(數值索引) | 否 | 僅能透過 getBehaviors() 遍歷移除 |
核心方法鏈:
Component::behaviors() — 回傳行為配置陣列Component::ensureBehaviors() — 確保行為已綁定(多處魔術方法調用前會呼叫)Component::attachBehaviorInternal() — 內部實際綁定邏輯(private)Behavior::attach() — 設定 owner、掛載事件處理器ensureBehaviors() 關鍵邏輯:
public function ensureBehaviors() {
if ($this->_behaviors === null) {
$this->_behaviors = [];
foreach ($this->behaviors() as $name => $behavior) {
$this->attachBehaviorInternal($name, $behavior);
}
}
}
attachBehaviorInternal() 核心職責:
Yii::createObject() 實例化_behaviors[]detach() 舊行為再綁定新行為(後綁定者勝出)$behavior->attach($this) 完成雙向綁定與事件掛載Behavior::attach() 兩大動作:
public function attach($owner) {
$this->owner = $owner; // 1. 設定擁有者,行為可反向操作元件
foreach ($this->events() as $event => $handler) {
$owner->on($event, is_string($handler) ? [$this, $handler] : $handler); // 2. 掛載事件
}
}
behaviors();動態綁定:呼叫 attachBehaviors();配置綁定:as 關鍵字owner 反向引用 + 掛載事件處理器理解這些底層機制,能幫你在複雜專案中精準控制 Behavior 生命週期,避免常見的重複綁定、事件洩漏等問題。