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()
的代码。这里因为只是具体功能实现,对于行为的理解关系不大。 就不把代码粘出来占用篇幅了。
行为的属性和方法注入原理