yii2项目实战-行为的理解

前文框架的配置以及user组件的配置中我们就多次抛出行为的概念,再加上上一节我们文末的引子,相信很多小伙伴都很期待行为到底是个什么东东。今天我们就揭开它的面纱,看看行为到底是什么!

行为,我们看下百度百科给出的基本解释:谓举止行动;指受思想支配而表现出来的外表活动。如:做出动作,发出声音,作出反应。

再来看下官方是如何定义的:行为是 yii\base\Behavior 或其子类的实例。 行为,也称为 mixins, 可以无须改变类继承关系即可增强一个已有的 yii\base\Component 类功能。 当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们。 此外,行为通过组件能响应被触发的事件, 从而自定义或调整组件正常执行的代码。

官方就是官方,没信心的同学看完估计脑子都蒙了有木有!

提醒:官方这里定义中描述的 “组件” 并非是 我们以前接触的components配置,这里所说的组件是 yii\base\Component 子类的意思哦。

我们用自己的话再来概括行为:实质就是一个类(yii\base\Behavior 或其子类的实例),通过某些特殊方式(注入,绑定),同另一个类(yii\base\Component 或其子类的实例)进行了绑定,然后二者可以进行交互。这句话你可以多看两遍,最后心里先明白,谁和谁绑定了。

那为啥要使用行为呢?行为有啥好处?行为,就是对当前类进行一个扩展,而且不用修改当前类!听起来是不是很玄乎?现在再结合一下我们上文说的100个控制器的问题,是不是豁然间就明白行为是什么啦?

我们来一个例子加深下理解。

backend\components 目录下新增一个类文件 MyBehavior.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace backend\components;

use Yii;

class MyBehavior extends \yii\base\ActionFilter
{
public function beforeAction ($action)
{
var_dump(111);
return true;
}
}

很简单,我们定义了一个名为MyBehavior,继承yii\base\ActionFilter的类。具体看下文详细分析。

然后修改 BlogController 的 behaviors 方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
public function behaviors()
{
return [
//附加行为
'myBehavior' => \backend\components\MyBehavior::className(),
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}

此时我们访问下 /index.php?r=blog 会发现,页面的最上面有打印111出来。咦?发生了什么?我们来分析下。

首先我们在 backend\components 下创建了一个类文件,就是一个类,我们给这个类起一个名字,行为类。前面我们给出了行为类的含义,就是一个继承了 yii\base\Behavior 或其子类的实例。我们看下 MyBehavior 类的父类 \yii\base\ActionFilter,不难发现该类就是继承的 \yii\base\Behavior 类。如此,我们便定义好了一个行为类。该行为类只做了一件事,在 beforeAction 方法中打印111。行为类写好了,我们再看下他又是怎么跟 yii\base\Component 子类进行绑定的。

我们在BlogController方法中,重写了 behaviors 方法,behaviors 方法用来给当前类配置相关的行为类。通过查看源码发现,BlogController 是 \yii\base\Controller 的子类,而 \yii\base\Controller 又是 \yii\base\Component 的子类,这就验证了我们上面所说行为类是跟 \yii\base\Component 的子类进行绑定。

如此,行为类 backend\components\MyBehavior 便跟我们当前的控制器 BlogController 进行了绑定。绑定之后,BlogController 就可以使用 MyBehavior 的属性和方法了,又由于是 beforeAction,所以就很自然的在 blog/index 操作执行之前调用啦。即页面顶部有输出 111 的现象。通过这个案例,你明白了行为到底是怎么回事了么?不明白也心有八九了,我们再来看一下如何手动调用行为类的方法。

假设 MyBehavior 依然附加在 BlogController中 ,我们在 MyBehavior 类中添加一个判断用户是否是访客的方法,看看如何在 BlogController 的 index 操作中去同行为类进行交互。

MyBehavior 的 isGuest 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function isGuest ()
{
return Yii::$app->user->isGuest;
}
BlogController 的 index 操作的部分代码

public function actionIndex()
{
$myBehavior = $this->getBehavior('myBehavior');
$isGuest = $myBehavior->isGuest();
var_dump($isGuest);

// 或者你也可以这样直接调用
$isGuest = $this->isGuest();
var_dump($isGuest);

// ......
}

到此,你明白如何定义行为类以及如何操作行为类了么?

当然,行为的附加以及移除还有其他几种方式,我们就先介绍到这里,其他几种大同小异,有什么不懂的下面给我留言。

下一章节,我们准备通过行为,来解决rbac的分配问题!