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绑定)
57 0
|
5月前
|
设计模式 JSON 前端开发
SSMP整合案例第四步 表现层controller开发及用Result进行统一消息处理
SSMP整合案例第四步 表现层controller开发及用Result进行统一消息处理
58 2
TP5.1门面类facade钩子behavior工具类,逻辑层service
TP5.1门面类facade钩子behavior工具类,逻辑层service
336 0
TP5.1门面类facade钩子behavior工具类,逻辑层service
|
Web App开发 JavaScript 前端开发
给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler
    写自定义控件已经好久了,也有几个用得时间比较长的,但是对于“事件”一直是比较模糊,没有很详细的理解。          最近升级分页控件,由于原来使用的是VB.net(在VB.net里面添加一个事件是比较容易的),现在想改用C#,而原来的方法又写得比较笨拙,想换一个更简洁一点的方法,所以不得不重新认识一下事件。
975 0
|
前端开发 JavaScript
2017年第1贴:EXT.JS使用MVC模式时,注意如何协调MODEL, STORE,VIEW,CONTROLLER的关系
也调了快一天,死活找不到窍门。 MODEL, STORE,VIEW的调置测试了很久,试了N种方法,不得其果。 最后,试着在APPLICATION里加入CONTROLLER, 在CONTROLLER里加入相应的STORE和VIEW支持, 搞定。
1260 0