YII2.0框架行为(Behavior)深入详解(10)
从上面的代码中可以看出,Yii还是先是调用了 $this->ensureBehaviors()
确保行为已经绑定。
然后,也是遍历 yii\base\Component::$_behaviros[]
数组。 通过 hasMethod()
方法判断方法是否存在。 如果所绑定的行为中要调用的方法存在,则使用PHP的 call_user_func_array()
调用之。 至于 hasMethod() 方法,我们后面再讲。
注入属性与方法的访问控制
在前面我们针对行为中public和private、protected的成员在所绑定的类中是否可访问举出了具体例子。 这里我们从代码层面解析原因。
在上面的内容,我们知道,一个属性可不可访问,主要看行为的 canGetProperty()
和 canSetProperty()
。 而一个方法可不可调用,主要看行为的 hasMethod() 。 由于 yii\base\Behavior 继承自我们的老朋友 yii\base\Object ,所以上面提到的三个判断方法, 事实上代码都在 Object 中。我们一个一个来看:
public function canGetProperty($name, $checkVars = true) { return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name); } public function canSetProperty($name, $checkVars = true) { return method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name); } public function hasMethod($name) { return method_exists($this, $name); }
这三个方法真的谈不上复杂。对此,我们可以得出以下结论:
- 当向Component绑定的行为读取(写入)一个属性时,如果行为为该属性定义了一个getter (setter),则可以访问。 或者,如果行为确实具有该成员变量即可通过上面的判断,此时,该成员变量可为 public, private, protected。 但最终只有 public 的成员变量才能正确访问。原因在上面讲注入的原理时已经交待了。
- 当调用Component绑定的行为的一个方法时,如果行为已经定义了该方法,即可通过上面的判断。 此时,这个方法可以为 public, private, protected。 但最终只有 public 的方法才能正确调用。如果你理解了上一款的原因,那么这里也就理解了。
行为与继承和特性(Traits) 的区别
从实现的效果看,你是不是会认为Yii真是多此一举?PHP中要达到这样的效果,可以使用继承呀,可以使用PHP新引入的特性(Traits)呀。但是,行为具有继承和特性所没有的优点,从实际使用的角度讲,继承和特性更靠底层点。靠底层,就意味着开发效率低,运行效率高。行为的引入,是以可以接受的运行效率牺牲为成本,谋取开发效率大提升的一笔买卖。
行为与继承