qiuxis 2016-12-10 14:11:00 1089次浏览 4条回复 8 2 0
  • 一、胡乱的说YII2 的行为

想必大家都看过机器猫这部动画片吧,机器猫有个四次元口袋,里面有很多流弊的道具,什么:时光穿梭机、隐身披风、放大缩小灯等等
每次看动画都想知道这次会从口袋里面拿啥玩意出来。
YII2的 behavior 好比四次元口袋 —— 正式点说法叫 mixin ,这个不懂可以自行百度。
怎么说呢?
有了这个口袋可以做很多原本无法做的事情,
有了时光穿梭机可以到过去某个时刻...
有了隐身功能,偷看静香洗澡就不会被发现了...
有了放大缩小灯,可以把汽车缩小...

  • 二、正经的说YII2 的行为

行为说白了就是组件的扩展,可以对组件的属性、方法、事件进行扩展而无需改动组件现有的代码逻辑。
也就是说行为的属性、方法、事件都会绑定到组件里头。
YII2 的行为一定程度上也是对Event 的封装
我们可以在行为里面定义需要扩展的属性、方法、也可以注册事件,让组件可以绑定行为,注册某事件的功能。

所以YII2的 behavior 能增强某个类原本没有的功能 ——
当行为附加到组件后,将"注入"它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们,披上"袈裟"就可以做坏事了
此外,行为通过组件能响应被触发的事件,从而自定义或调整组件正常执行的代码。
比如:绑定了 TimeStampBehavior ,我们在插入和更新数据的时候时间会自动加入,是不是特6...

说的这么多需要注意这几个关键词:行为、组件、属性、方法、事件

行为条件 :yii\base\Behavior 或其子类的实例
组件条件 :yii\base\Component 或其子类的实例
属性条件 :行为里定义
方法条件 :行为里定义
事件条件 :行为里定义

只有条件满足后才能去执行某件事

  • 三、打比方举栗子

行为1 behavior1 四次元口袋
组件1 component1 机器猫
组件2 component2 大雄
控制器 AuthorController 作者(藤子·F·不二雄)

这样去解释就知道为什么哆啦A梦和大雄能力那么强大了,他们能用四次元口袋里面的道具呀!
这里还要知道一点,就是机器猫可以拥有不止一个四次元口袋,可以多个!
机器猫、大雄有多个四次元口袋,拥有多个功能,这样作者就可以根据需要来让这几个角色去做很多事了。

  • 四、附加行为的方式

怎么获取到这个四次元口袋呢?
有三种方式来获取:

1、可以通过配置附加行为:

component配置项及里面的子项里

<?php
[
    'class' => 'path\to\ClassName',
    'propertyName' => 'propertyValue',
    'as myBehavior2' => MyBehavior::className(),
    'as myBehavior3' => [
        'class' => MyBehavior::className(),
        'prop1' => 'value1',
        'prop2' => 'value2',
    ],
]
?>

2、动态附加行为

<?php 
use app\components\MyBehavior;

// 附加行为对象
$component->attachBehavior('myBehavior1', new MyBehavior);

// 附加行为类
$component->attachBehavior('myBehavior2', MyBehavior::className());

// 附加配置数组
$component->attachBehavior('myBehavior3', [
    'class' => MyBehavior::className(),
    'prop1' => 'value1',
    'prop2' => 'value2',
]);

// 批量绑定
$component->attachBehaviors([
    'myBehavior1' => new MyBehavior,  // 这是一个命名行为
    MyBehavior::className(),          // 这是一个匿名行为
]);
?>

3、静态附加行为

<?php 
/**
要静态附加行为,覆写行为要附加的组件类的 yii\base\Component::behaviors() 方法即可。
yii\base\Component::behaviors() 方法应该返回行为配置列表。每个行为配置可以是行为类名也可以是配置数组。
**/
namespace app\models;

use yii\db\ActiveRecord;
use app\components\MyBehavior;

class User extends ActiveRecord
{
    public function behaviors()
    {
        return [
            // 匿名行为,只有行为类名
            MyBehavior::className(),

            // 命名行为,只有行为类名
            'myBehavior2' => MyBehavior::className(),

            // 匿名行为,配置数组
            [
                'class' => MyBehavior::className(),
                'prop1' => 'value1',
                'prop2' => 'value2',
            ],

            // 命名行为,配置数组
            'myBehavior4' => [
                'class' => MyBehavior::className(),
                'prop1' => 'value1',
                'prop2' => 'value2',
            ]
        ];
    }
}
?>
  • 五、使用实例

使用行为的大致流程:拢共分四步

1.从 yii\base\Component 派生自己的类,以便使用行为
2.从 yii\base\Behavior 派生自己的行为类,里面定义行为涉及到的属性、方法
3.将Component和Behavior绑定起来
4.像使用Component自身的属性和方法一样,尽情使用行为中定义的属性和方法

用实例说明

  • 六、与 Traits 的对比

1、胡乱的对比

我们都知道变种人金刚狼罗根有不死身和可伸缩的利爪,这是由于父母的基因遗传给他的,想去也去不掉啊,所以金刚狼很少跟女朋友嘿嘿嘿
因为出过意外啊,有一次太激动爪子就把自己的女人给弄伤了,很危险...
另外罗根本来的骨骼是一般骨骼,后来注入了艾德曼合金才拥有了合金骨架,不过差点被搞死

如果大雄拿了四次元的口袋也来一副金刚爪我觉得也是可以的,再穿件刀枪不入的衣服,说不定这个四次元口袋也有长生不老药呢,把大雄打造成金刚狼完全没问题,这些功能拆卸很简单,而且升级改造方便,也不会遇到金刚狼的尴尬...
但是大雄和金刚狼比起来也有劣势,那就是一个是借助外力,另外一个是天生的,所以使用起来在速度上可能会稍逊一筹了。

2、真正的对比《深入理解Yii2.0》

行为从本质上讲,也是PHP的类,因此一个行为可以继承自另一个行为,从而实现代码的复用。而特性只是PHP的一种语法,效果上类似于把特性的代码导入到了类中从而实现代码的注入,特性是不支持继承的。
行为可以动态地绑定、解除,而不必要对类进行修改。但是特性必须在类里面使用 use 语句,要解除特性时,则要删除这个语句。换句话说,需要对类进行修改。
行为还以在在配置阶段进行绑定,特性就不行了。
行为可以用于对事件进行反馈,而特性不行。
当出现命名冲突时,行为会自行排除冲突,自动使用先绑定的行为。而特性在发生冲突时,需要人为干预,修改发生冲突的变量名、属性名、方法名。
倾向于使用特性的情况:

特性比行为在效率上要高一点,因为行为其实是类的实例,需要时间和空间进行分配。
特性是PHP的语法,因此,IDE的支持要好一些。目前还没有IDE能支持行为。

yii2 行为 behavior (2) —— yii2启示录
yii2 行为 behavior (3) —— yii2启示录

觉得很赞
您需要登录后才可以回复。登录 | 立即注册
在线
277