今天不讲内容,仅仅分享一下混乱的beforeAction,希望对各位有所帮助。
昨天发文后,某同学私下问的一个问题,我简单描述一下。
配置yii2-admin组件的时候,有一项关于行为的配置,如下1
2
3
4
5
6
7'as access' => [
'class' => 'mdm\admin\components\AccessControl',
'allowActions' => [
//这里是允许访问的action
'*'
]
],
之前配置过yii2-admin组件的应该都不陌生,没配置过的也没关系,看主要问题。
在上文介绍的执行请求过程中,这个行为它是从哪一步开始执行的,mdm\admin\components\AccessControl::beforeAction为什么会自动执行,为什么我给一个继承自 yii\base\Behavior 的行为添加的beforeAction 方法不会自动执行呢?
首先能这么问,肯定思考了,动手实践了,这很好,也希望大家在阅读的过程中,多多分析,多多留言。
来看一下这个问题。
上文我们在介绍 yii\base\Controller::runAction方法时说过,调用controller级别的beforeAction事件,不知道各位还有没有印象。
这里说的controller级别的beforeAction事件,指的是yii\base\Controller::beforeAction方法内触发的 yii\base\Controller::EVENT_BEFORE_ACTION事件。
大家看一下yii\base\Controller::beforeAction 方法就明白我这话的意思了。1
2
3
4
5
6public function beforeAction($action)
{
$event = new ActionEvent($action);
$this->trigger(self::EVENT_BEFORE_ACTION, $event);
return $event->isValid;
}
我们回过头来看一下 mdm\admin\components\AccessControl 类的父类1
2
3class AccessControl extends \yii\base\ActionFilter
{
}
yii\base\ActionFilter,一种特殊的行为类,又称为过滤器。
过滤器是怎么跟 mdm\admin\components\AccessControl::beforeAction 扯到一块的呢?
前面分析行为的时候我们说过,为应用实例 yii\web\Application 配置的行为 “as “ + 行为名称,在应用预初始化阶段,其指向的行为类的attach方法都会被自动调用,不明白我在说啥的可以回去再看看行为一节。
也就是说 mdm\admin\components\AccessControl 的父类yii\base\ActionFilter::attach方法会在应用预初始化的时候自动调用。
yii\base\ActionFilter::attach方法代码如下1
2
3
4
5public function attach($owner)
{
$this->owner = $owner;
$owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
}
这里是为yii\base\Controller::EVENT_BEFORE_ACTION注册事件,对应的事件处理程序是1
yii\base\ActionFilter::beforeFilter。
注意哦,这个阶段仅仅是为 yii\base\Controller 注册事件 EVENT_BEFORE_ACTION。
有同学好像明白了什么。
yii\base\Controller::runAction 调用controller级别的beforeAction事件 ,继而触发 yii\base\Controller::EVENT_BEFORE_ACTION 事件,即在这一步调用了 yii\base\ActionFilter::beforeFilter。
yii\base\ActionFilter::beforeFilter 做了什么,我们注意到该方法中的一句代码1
$this->beforeAction($event->action);
$this 这里指的是 mdm\admin\components\AccessControl,所以这里就直接调用了 mdm\admin\components\AccessControl::beforeAction 。
同样,yii\base\Controller::EVENT_AFTER_ACTION 事件也是如此。
下面简单的梳理一下前后顺序:
…… => yii\base\ActionFilter::attach => …… => yii\base\Module::beforeAction => yii\base\ActionFilter::beforeFilter => mdm\admin\components\AccessControl::beforeAction => yii\web\Controller::beforeAction => yii\base\Controller::beforeAction => ……