yii\base\Compoent::behaviros()
来预先注入一些行为。 那么,这个函数会将这些行为先注入进来。
从上面的代码中,自然就看到了接下来要说的第三个东东, yii\base\Component\attachBehaviorInternal()
:
private function attachBehaviorInternal($name, $behavior) { // 不是 Behavior 实例,说是只是类名、配置数组,那么就创建出来吧 if (!($behavior instanceof Behavior)) { $behavior = Yii::createObject($behavior); } // 匿名行为 if (is_int($name)) { $behavior->attach($this); $this->_behaviors[] = $behavior; // 命名行为 } else { // 已经有一个同名的行为,要先解除,再将新的行为绑定上去。 if (isset($this->_behaviors[$name])) { $this->_behaviors[$name]->detach(); } $behavior->attach($this); $this->_behaviors[$name] = $behavior; } return $behavior; }
首先要注意到,这是一个private成员。其实在Yii中,所有后缀为 *Internal 的方法,都是私有的。 这个方法干了这么几件事:
- 如果 $behavior 参数并非是一个 Behavior 实例,就以之为参数,用
Yii::createObject()
创建出来。 - 如果以匿名行为的形式绑定行为,那么直接将行为附加在这个类上。
- 如果是命名行为,先看看是否有同名的行为已经绑定在这个类上,如果有,用后来的行为取代之前的行为。
在 yii\base\Component::attachBehaviorInternal()
中, 以 $this 为参数调用了 yii\base\Behavior::attach()
。 从而,引出了跟绑定相关的最后一个家伙 yii\base\Behavior::attach()
, 这也是前面我们讲行为的要素时没讲完的。先看看代码:
public function attach($owner) { $this->owner = $owner; foreach ($this->events() as $event => $handler) { $owner->on($event, is_string($handler) ? [$this, $handler] : $handler); } }
上面的代码干了两件事:
- 设置好行为的 $owner ,使得行为可以访问、操作所依附的对象
- 遍历行为中的
events()
返回的数组,将准备响应的事件,通过所依附类的on()
绑定到类上
说了这么多,关于绑定,做个小结:
- 绑定的动作从Component发起;
- 静态绑定通过重载
yii\base\Componet::behaviors()
实现; - 动态绑定通过调用
yii\base\Component::attachBehaviors()
实现; - 行为还可以通过为 Component 配置 as 配置项进行绑定;
- 行为有匿名行为和命名行为之分,区别在于绑定时是否给出命名。 命名行为可以通过其命名进行标识,从而有针对性地进行解除等操作;