资讯专栏INFORMATION COLUMN

Yii源码解读-行为

IntMain / 2043人阅读

摘要:行为所要响应的事件重载方法,表示这个行为将对类何种事件进行何种反馈。行为用的最多的,也是对于各种事件的响应。当出现命名冲突时,行为会自行排除冲突,自动使用先绑定的行为。目前还没有能支持行为。

Yii基础 行为(Behavior)

行为(behavior)可以在不修改现有类的情况下,对类的功能进行扩充。 通过将行为绑定到一个类,可以使类具有行为本身所定义的属性和方法,就好像类本来就有这些属性和方法一样。 而且不需要写一个新的类去继承或包含现有类。

Yii中的行为,是yiiaseBehavior中的实例,只要将Behavior实例绑定到Component实例上即可。但是,Behavior只能与Component类绑定。

如果你写了一个类,需要用到行为,那么必须要继承自yiiaseComponent

使用行为

Demo:

// 定义一个将绑定行为的类
class MyClass extends yiiaseComponent{}

//定义一个行为类,他将绑定到MyClass上
class MyBehavior extends yiiaseBehavior{
    public $property1 = "This is property in MyBehavior.";
    
    public function method1(){
        return "Method in MyBehavior is called.";
    }
}

$myClass = new MyClass();
$myBehavior = new MyBehavior();

// Bind
$myClass->attachBehavior("myBehavior", $myBehavior);

// 访问
echo $myClass->property1;
echo $myClass->method1();

使用行为的大致流程:

yiiaseComponent派生自己的类,以便使用行为。

yiiaseBehavior派生自己的行为类,定义属性和方法。

将Component和Behavior绑定起来

像使用Behavior一样使用Component

行为的要素

$owner:指向行为的依附对象

events():行为所有要响应的事件

attach():将行为与Component绑定起来

detach():你懂的

行为的依附对象

在行为的方法中, $this 引用的是行为本身, 试图通过 $this 来访问行为所依附的Component是行不通的。 正确的方法是通过yiiaseBehavior::$owner来访问Component。

行为所要响应的事件

重载yiiaseBehavior::events()方法,表示这个行为将对类何种事件进行何种反馈。

namespace appComponents;

use yiidbActiveRecord;
use yiiaseBehavior;

class MyBehavior extends Behavior{
    // 重载,使得事件触发时,调用行为中的一些方法
    public function events(){
        // 在AR的这个事件触发时,调用成员函数beforeValidate
        return [ActiveRecord::EVENT_BEFORE_VALIDATE => "beforeValidate"]
    }
    
    // 行为的成员函数
    public function beforeValidate($events){...}
}
行为的绑定和解除

绑定和解除,均需要行为和Component双方共同参与才行。

实际操作,Behavior分别使用attach()detach()来实现即可。

定义一个行为

定义一个行为,即是准备好注入到现有类的属性和方法。即要写一个Behavior的子类

namespace appComponents;
use yiiaseBehavior;

class MyBehavior extends Behavior{
    public $prop1;
    
    private $_prop2;
    private $_prop3;
    private $_prop4;
    
    public function getProp2(){
        return $this->prop2;
    }
    
    public function setProp3($value){
        $this->_prop3 = $value;
    }
    
    public function foo(){}
    
    protected function bar(){}
}

该子类继承了Behavior,同时间接的继承了Object。当该类与Component绑定后,Component也就拥有了相对应public的属性和方法,而private和protected的属性和方法并不能得到。

行为的绑定

有两种方法可以将一个Behavior绑定到一个yiiaseComponent上。

静态方法:在代码没有跑起来之前

静态绑定,只需要重载yiiaseComponent::bahaviors()就可以了。该方法描述类所具有的行为。描述方法:

配置来描述

Behavior类名

Behavior类的配置数组

namespace appmodels;
use yiidbActiveRecord;
use appComponentsMyBehavior;

class User extends ActiveRecord{
    public function behaviors(){
        return [
            // 匿名行为
            MyBehavior::className(),
            // 名为myBehavior2的行为
            "myBehavior2" => MyBehavior::className(),
            // 匿名行为 + 给出配置数组
            [
                "class" => MyBehavior::className(),
                "prop1" => "v1",
                "prop3" => "v3",
            ],
            // 带名称的行为 + 配置数组
            "myBehavior4" => [
                "class" => MyBehavior::className(),
                "prop1" => "v1",
                "prop3" => "v3"
            ]
        ];
    }
}

另外通过配置文件:

[
    "as myBehavior2" => MyBehavior::className(),
]
动态方法绑定行为

需要调用yiiaseComponent::attachBehaviors()

$Component->attachBehaviors([
    "myBehavior1" => new MyBehavior,
]);
$behavior = $Component->getBehavior("myBehavior1");
绑定的内部原理

yiiaseComponent::behaviors()

yiiaseComponent::ensureBehaviors()

yiiaseComponent::attachBehaviorInternal()

yiiaseBehavior::attach()

关于绑定,做个小结:

绑定的动作从Component发起;

静态绑定通过重载 yiiaseComponet::behaviors() 实现;

动态绑定通过调用 yiiaseComponent::attachBehaviors() 实现;

行为还可以通过为 Component 配置 as 配置项进行绑定;

行为有匿名行为和命名行为之分,区别在于绑定时是否给出命名。 命名行为可以通过其命名进行标识,从而有针对性地进行解除等操作;

绑定过程中,后绑定的行为会取代已经绑定的同名行为;

绑定的意义有两点,一是为行为设置 $owner 。二是将行为中拟响应的事件的handler绑定到类中去。

行为响应的事件实例

绑定和解除的过程,实际上就是将行为中的事件handler绑定到类中去。行为用的最多的,也是对于Component各种事件的响应。

行为的属性和方法注入原理

__get(), __set(), __call()

行为与继承和特性(Traits)的区别

相比较于使用继承的方式来扩充类功能,使用行为的方式,一是不必对现有类进行修改,二是PHP不支持多继承,但是Yii可以绑定多个行为,从而达到类似多继承的效果。

倾向于使用行为的情况:

行为从本质上讲,也是PHP的类,因此一个行为可以继承自另一个行为,从而实现代码的复用。而特性只是PHP的一种语法,效果上类似于把特性的代码导入到了类中从而实现代码的注入,特性是不支持继承的。

行为可以动态地绑定、解除,而不必要对类进行修改。但是特性必须在类在使用 use 语句,要解除特性时,则要删除这个语句。换句话说,需要对类进行修改。

行为还以在在配置阶段进行绑定,特性就不行了。

行为可以用于对事件进行反馈,而特性不行。

当出现命名冲突时,行为会自行排除冲突,自动使用先绑定的行为。而特性在发生冲突时,需要人为干预,修改发生冲突的变量名、属性名、方法名。

倾向于使用特性的情况:

特性比行为在效率上要高一点,因为行为其实是类的实例,需要时间和空间进行分配。

特性是PHP的语法,因此,IDE的支持要好一些。目前还没有IDE能支持行为。

参考

http://www.digpage.com/behavior.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21435.html

相关文章

  • Yii源码解读-环境&配置

    摘要:环境需要了解一下一个纯粹的与本地环境密切相关的配置项。对于配置项以数组进行组织。数组元素表示将要创建的对象的完整类名。数组元素表示指定为属性的初始值为。数组元素表示将绑定到对象的事件中。对于形式配置项,视配置值为一个事件,绑定到上。 环境 需要了解一下cookieValidationKey:一个纯粹的、与本地环境密切相关的配置项。 但是,在有些情况下,cookieValidationK...

    cgh1999520 评论0 收藏0
  • Yii源码解读-属性

    摘要:成员变量可以视为一个可读可写没有任何预处理或后处理的属性。而成员变量由于外部不可见,与属性外的特性不相符,所以不能视为属性。在一些表示数据结构数据集合等简单情况下,且不需读写控制等,可以考虑使用成员变量作为属性,这样可以提高一点效率。 Yii基础 属性 property 属性用于表征类的状态,从访问的形式上看,属性与成员变量没有区别。但是,成员变量是就类的结构构成而言的概念,而属性是就...

    instein 评论0 收藏0
  • Yii源码解读 - 事件

    摘要:事件的绑定和解除对事件进行绑定和解绑。使用全局函数作为来进行绑定使用对象的成员函数来进行绑定使用类的静态成员函数进行绑定使用匿名函数上面的数组是用来维护事件数组。事件的级别类级别事件类级别事件用于响应所有类实例的事件。 Yii基础 事件 event 使用事件,可以在特定的时点,触发执行预先设定的一段代码,事件既是代码解耦的一种方式,也是设计业务流程的一种模式。 事件的相关要素 这是一...

    AaronYuan 评论0 收藏0
  • Yii源码解读-别名

    摘要:设置别名的目的特殊的变量常量保存整个应用的所有别名。别名的解析过程先按根别名找到可能保存别名的分支。别名必然以打头。别名解析时,优先匹配较长的别名。使用别名时,要将别名放在最前面,不能放在中间。 Alias 设置别名的目的:特殊的变量常量 yiiBaseYii::$aliases保存整个Yii应用的所有别名。 在yiiaseApplication的构造函数__construct()中...

    banana_pi 评论0 收藏0
  • Yii源码解读-类自动加载

    摘要:实现的类自动加载,依赖于的,注册一个自己的自动加载函数,并插入到自动加载函数栈的最前面,确保的会被最先调用。首先加载第三方的,再加载的。最后加载的,这样可以保证的优先加载。 实现 Yii的类自动加载,依赖于PHP的spl_autoload_register(), 注册一个自己的自动加载函数(autoloader),并插入到自动加载函数栈的最前面,确保Yii的autoloader会被最先...

    Jeffrrey 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<