public function events()
{
return array_fill_keys(array_keys($this->attributes),
'evaluateAttributes');
}
这段代码的意思这里不作过多深入,学有余力的读者朋友可以自行研究,难度并不高。 这里,你只需要大致知道,这段代码将返回一个数组,其键值为 $this->attributes 数组的键值, 数组元素的值为成员函数evaluateAttributes 。
而在 yii\behaviors\TimeStampBehavior::init() 中,有以下的代码:
public function init()
{
parent::init();
if (empty($this->attributes)) {
// 重点看这里
$this->attributes = [
BaseActiveRecord::EVENT_BEFORE_INSERT =>
[$this->createdAtAttribute, $this->updatedAtAttribute],
BaseActiveRecord::EVENT_BEFORE_UPDATE =>
$this->updatedAtAttribute,
];
}
}
上面的代码重点看的是对于 $this->attributes 的初始化部分。 结合上面2个方法的代码,对于yii\base\Behavior::events() 的返回数组,其格式应该是这样的:
return [ BaseActiveRecord::EVENT_BEFORE_INSERT => 'evaluateAttributes', BaseActiveRecord::EVENT_BEFORE_UPDATE => 'evaluateAttributes', ];
数组的键值用于指定要响应的事件, 这里是 BaseActiveRecord::EVENT_BEFORE_INSERT 和BaseActiveRecord::EVENT_BEFORE_UPDATE 。 数组的值是一个事件handler,如上面的 evaluateAttributes 。
那么一旦TimeStampBehavior与某个ActiveRecord绑定,就会调用 yii\behaviors\TimeStampBehavior::attach() , 那么就会有:
// 这里 $owner 是某个 ActiveRecord
public function attach($owner)
{
$this->owner = $owner;
// 遍历上面提到的 events() 所定义的数组
foreach ($this->events() as $event => $handler) {
// 调用 ActiveRecord::on 来绑定事件
// 这里 $handler 为字符串 `evaluateAttributes`
// 因此,相当于调用 on(BaseActiveRecord::EVENT_BEFORE_INSERT,
// [$this, 'evaluateAttributes'])
$owner->on($event, is_string($handler) ? [$this, $handler] :
$handler);
}
}
因此,事件 BaseActiveRecord::EVENT_BEFORE_INSERT 和 BaseActiveRecord::EVENT_BEFORE_UPDATE 就绑定到了ActiveRecord上了。当新建记录或更新记录时, TimeStampBehavior::evaluateAttributes 就会被触发。 从而实现时间戳的功能。具体可以看看 yii\behaviors\AttributeBehavior::evaluateAttributes() 和yii\behaviors\TimeStampBehavior::getValues() 的代码。这里因为只是具体功能实现,对于行为的理解关系不大。 就不把代码粘出来占用篇幅了。
行为的属性和方法注入原理
