Yii2 分析Controller::behaviors 触发过程

简介: 版本示例客户端请求后的运行流程简述1 版本// yii\BaseYii\getVersionpublic static function getVersion(){ return '2.0.10';}2 示例AccessControl是框架自带的,位于yii\filters目录下class SiteC

1 版本

// yii\BaseYii\getVersion
public static function getVersion()
{
    return '2.0.10';
}

2 示例

AccessControl是框架自带的,位于yii\filters目录下

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => ['login', 'error', 'register', 'offline'],
                        'allow' => true,
                    ],
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ]
                ]
            ]
        ];
    }
}

3 客户端请求后的运行流程

具体运行流程请参考Yii2分析运行流程
http://blog.csdn.net/alex_my/article/details/54142711

最终会在yii\base\Module::runAction中
创建controller, action
然后执行$controller->runAction

public function runAction($route, $params = [])
{
    $parts = $this->createController($route);
    if (is_array($parts)) 
    {
        list($controller, $actionID) = $parts;
        Yii::$app->controller = $controller;
        $result = $controller->runAction($actionID, $params);
        ...
    }
    ...
}


runAction中的流程请参考Yii理解Controller
http://blog.csdn.net/alex_my/article/details/54138744

在yii\base\Controller::runAction中
会执行 this->beforeAction —> this->ensureBehaviors()
将SiteController::behaviors()中的行为绑定到SiteController上

public function ensureBehaviors()
{
    if ($this->_behaviors === null) {
        $this->_behaviors = [];
        foreach ($this->behaviors() as $name => $behavior) {
            $this->attachBehaviorInternal($name, $behavior);
        }
    }
}
private function attachBehaviorInternal($name, $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();
        }
        // ---------------- 这个名为access的行为将会执行到这里
        $behavior->attach($this);
        $this->_behaviors[$name] = $behavior;
    }
    return $behavior;
}


$behaviors实际上是AccessControl的对象,attach是其基类ActionFilter中的函数

// yii\base\ActionFilter::attach
public function attach($owner)
{
    $this->owner = $owner;
    $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
}

将会执行ActionFilter::beforeFilter

public function beforeFilter($event)
{
    ...
    $event->isValid = $this->beforeAction($event->action);
    ...
}

AccessControl重载了beforeAction函数

// yii\filters\AccessControl::beforeAction
public function beforeAction($action)
{
    $user = $this->user;
    $request = Yii::$app->getRequest();
    // 这些就是在SiteController中定义的规则
    foreach ($this->rules as $rule) 
    {
        if ($allow = $rule->allows($action, $user, $request)) 
        {
            return true;
        } 
        elseif ($allow === false) 
        {
            if (isset($rule->denyCallback)) 
            {
                call_user_func($rule->denyCallback, $rule, $action);
            } 
            elseif ($this->denyCallback !== null) 
            {
                call_user_func($this->denyCallback, $rule, $action);
            } 
            else 
            {
                $this->denyAccess($user);
            }
            return false;
        }
    }
    if ($this->denyCallback !== null) 
    {
        call_user_func($this->denyCallback, null, $action);
    }
    else 
    {
        $this->denyAccess($user);
    }
    return false;
}

4 简述

简单的说就是会在执行controller中的action(比如SiteController::actionIndex)之前, 会先执行这些behaviors, 如果没有通过, 则action不会继续执行下去。

相关文章
14avalon - 指令ms-controller (controller绑定)
14avalon - 指令ms-controller (controller绑定)
65 0
|
8月前
|
SQL Java 调度
SpringBoot集成quartz定时任务trigger_state状态ERROR解决办法
SpringBoot集成quartz定时任务trigger_state状态ERROR解决办法
|
8月前
|
JavaScript 前端开发 API
「深入探究Web页面生命周期:DOMContentLoaded、load、beforeunload和unload事件」
在 Web 开发中,了解页面生命周期是非常重要的。页面生命周期定义了页面从加载到卸载的整个过程,包括各种事件和阶段。在本文中,我们将详细介绍四个关键事件:DOMContentLoaded、load、beforeunload 和 unload。我们将探讨这些事件的属性、API、应用场景,并提供一些代码示例和参考资料。
|
Kubernetes 容器
【K8s源码品读】002:Phase 1 - kubectl - create的调用逻辑
我们的目标是查看`kubectl create -f nginx_pod.yaml` 这个命令是怎么运行的。
65 0
|
移动开发 小程序
关于uni-app页面Page和组件Component生命周期执行的先后顺序
关于uni-app页面Page和组件Component生命周期执行的先后顺序
165 0
|
Java Android开发 C++
Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION
Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION
330 0
Yii2.0的默认控制器是什么?底层原理是什么?
Yii2.0的默认控制器是什么?底层原理是什么?
|
数据库连接
Yii2.0框架中如何进行事件处理?它支持哪些事件?
Yii2.0框架中如何进行事件处理?它支持哪些事件?
213 0
|
Java 测试技术 C#
WPF的APP生命周期以及全局异常捕获
WPF的APP生命周期以及全局异常捕获,详细介绍了整个APP的生命周期和窗体生命周期,以及如何使用全局异常捕获
254 0
TP5.1门面类facade钩子behavior工具类,逻辑层service
TP5.1门面类facade钩子behavior工具类,逻辑层service
346 0
TP5.1门面类facade钩子behavior工具类,逻辑层service

热门文章

最新文章