加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP的Yii框架中行为的定义和绑定方法讲解

发布时间:2022-02-25 10:29:38 所属栏目:PHP教程 来源:互联网
导读:定义行为 要定义行为,通过继承 yii/base/Behavior 或其子类来建立一个类。如: namespace app/components; use yii/base/Behavior; class MyBehavior extends Behavior { public $prop1; private $_prop2; public function getProp2() { return $this-_pr
  定义行为
 
  要定义行为,通过继承 yii/base/Behavior 或其子类来建立一个类。如:
 
  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()
  
    {
  
      // ...
  
    }
  
  }
  以上代码定义了行为类 app/components/MyBehavior 并为要附加行为的组件提供了两个属性 prop1 、 prop2 和一个方法 foo()。注意属性 prop2 是通过 getter getProp2() 和 setter setProp2() 定义的。能这样用是因为 yii/base/Object 是 yii/base/Behavior 的祖先类,此祖先类支持用 getter 和 setter 方法定义属性
 
  提示:在行为内部可以通过 yii/base/Behavior::owner 属性访问行为已附加的组件。
 
  静态方法绑定行为
 
  静态绑定行为,只需要重载 yii/base/Component::behaviors() 就可以了。 这个方法用于描述类所具有的行为。如何描述呢? 使用配置来描述,可以是Behavior类名,也可以是Behavior类的配置数组:
 
  namespace app/models;
 
  
  use yii/db/ActiveRecord;
  
  use app/Components/MyBehavior;
 
  class User extends ActiveRecord
  
  {
  
    public function behaviors()
  
    {
  
      return [
  
        // 匿名的行为,仅直接给出行为的类名称
  
        MyBehavior::className(),
  
    
  
        // 名为myBehavior2的行为,也是仅给出行为的类名称
  
        'myBehavior2' => MyBehavior::className(),
   
  
        // 匿名行为,给出了MyBehavior类的配置数组
  
        [
  
          'class' => MyBehavior::className(),
  
          'prop1' => 'value1',
  
          'prop3' => 'value3',
  
        ],
  
    
  
        // 名为myBehavior4的行为,也是给出了MyBehavior类的配置数组
  
        'myBehavior4' => [
  
          'class' => MyBehavior::className(),
  //Cuoxin.com
          'prop1' => 'value1',
  
          'prop3' => 'value3',
  
        ]
  
      ];
  
    }
  
  }
  还有一个静态的绑定办法,就是通过配置文件来绑定:
 
  [
  
    'as myBehavior2' => MyBehavior::className(),
  
    'as myBehavior3' => [
  
      'class' => MyBehavior::className(),
  
      'prop1' => 'value1',
  
      'prop3' => 'value3',
  
    ],
  
  ]
  动态方法绑定行为
 
  动态绑定行为,需要调用 yii/base/Compoent::attachBehaviors():
 
  $Component->attachBehaviors([
  
    'myBehavior1' => new MyBehavior, // 这是一个命名行为
  
    MyBehavior::className(),     // 这是一个匿名行为
  
  ]);
  这个方法接受一个数组参数,参数的含义与上面静态绑定行为是一样一样的。
 
  在上面的这些例子中,以数组的键作为行为的命名,而对于没有提供键名的行为,就是匿名行为。
 
  对于命名的行为,可以调用 yii/base/Component::getBehavior() 来取得这个绑定好的行为:
 
  $behavior = $Component->getBehavior('myBehavior2');
 
  对于匿名的行为,则没有办法直接引用了。但是,可以获取所有的绑定好的行为:
 
  $behaviors = $Component->getBehaviors();
 
  绑定的内部原理
 
  只是重载一个 yii/base/Component::behaviors() 就可以这么神奇地使用行为了? 这只是冰山的一角,实际上关系到绑定的过程,有关的方面有:
 
  yii/base/Component::behaviors()
  
  yii/base/Component::ensureBehaviors()
  
  yii/base/Component::attachBehaviorInternal()
  
  yii/base/Behavior::attach()
  4个方法中,Behavior只占其一,更多的代码,是在Component中完成的。
 
  yii/base/Component::behaviors() 上面讲静态方法绑定行为时已经提到了,就是返回一个数组用于描述行为。 那么 yii/base/Component::ensuerBehaviors() 呢?
 
  这个方法会在Component的诸多地方调用 __get() __set() __isset() __unset() __call() canGetProperty() hasMethod() hasEventHandlers() on() off() 等用到,看到这么多是不是头疼?一点都不复杂,一句话,只要涉及到类的属性、方法、事件这个函数都会被调用到。
 
  这么众星拱月,被诸多凡人所需要的 ensureBehaviors() 究竟是何许人也? 就像名字所表明的,他的作用在于“ensure” 。其实只是确保 behaviors() 中所描述的行为已经进行了绑定而已:
 
  public function ensureBehaviors()
  
  {
  
    // 为null表示尚未绑定
  
    // 多说一句,为空数组表示没有绑定任何行为
  
    if ($this->_behaviors === null) {
  
      $this->_behaviors = [];
  
      // 遍历 $this->behaviors() 返回的数组,并绑定
  
      foreach ($this->behaviors() as $name => $behavior) {
  
        $this->attachBehaviorInternal($name, $behavior);
  
      }
  
    }
  
  }
  这个方法主要是对子类用的, yii/base/Compoent 没有任何预先注入的行为,所以,这个调用没有用。 但是对于子类,你可能重载了 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 配置项进行绑定;
 
  行为有匿名行为和命名行为之分,区别在于绑定时是否给出命名。 命名行为可以通过其命名进行标识,从而有针对性地进行解除等操作;
 
  绑定过程中,后绑定的行为会取代已经绑定的同名行为;
 
  绑定的意义有两点,一是为行为设置 $owner 。二是将行为中拟响应的事件的handler绑定到类中去。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读