Yii2 分析运行流程

Posted 木子炜培先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Yii2 分析运行流程相关的知识,希望对你有一定的参考价值。

 

http://blog.csdn.net/alex_my/article/details/54142711

版本

创建Application

run过程

handleRequest

runAction

简述流程

1 版本

 

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

2

// web/index.php

new yii\web\Application($config)

// yii\base\Application.php

public function __construct($config = [])
{
    Yii::$app = $this;
    static::setInstance($this);

    $this->state = self::STATE_BEGIN;
    // 配置属性
    $this->preInit($config);
    // 注册error相关处理函数
    $this->registerErrorHandler($config);
    // 在基类的构造函数中将会调用init()函数
    // 在init()中直接调用bootstrap()函数
    // 先调用 web/Application::bootstrap()
    // 再调用 base/Application::bootstrap()
    Component::__construct($config);
}
//  base/Application::bootstrap()

protected function bootstrap()
{
    // 加载扩展清单中的文件, 默认使用 vendor/yiisoft/extensions.php
    if ($this->extensions === null) 
    {
        $file = Yii::getAlias(‘@vendor/yiisoft/extensions.php‘);
        $this->extensions = is_file($file) ? include($file) : [];
    }
    // 创建这些扩展组件
    // 如果这些组件实现了BootstrapInterface, 还会调用组件下的bootstrap函数
    foreach ($this->extensions as $extension)
    {
        if (!empty($extension[‘alias‘])) 
        {
            foreach ($extension[‘alias‘] as $name => $path) 
            {
                Yii::setAlias($name, $path);
            }
        }
        if (isset($extension[‘bootstrap‘])) 
        {
            $component = Yii::createObject($extension[‘bootstrap‘]);
            if ($component instanceof BootstrapInterface)
            {
                Yii::trace(‘Bootstrap with ‘ . get_class($component) . ‘::bootstrap()‘, __METHOD__);
                $component->bootstrap($this);
            } 
            else 
            {
                Yii::trace(‘Bootstrap with ‘ . get_class($component), __METHOD__);
            }
        }
    }

    // 加载将要运行的一些组件, 这些组件配置在main.php, main-local.php中
    // ‘bootstrap‘ => [‘log‘],
    // $config[‘bootstrap‘][] = ‘debug‘;
    // $config[‘bootstrap‘][] = ‘gii‘;
    // 开发模式下,默认加载3个: log, debug, gii
    // 从$config中的配置信息变成base\Application中的属性$bootstrap经历以下步骤:
    // Component::__construct  --> Yii::configure($this, $config)

    foreach ($this->bootstrap as $class) 
    {
        $component = null;
        if (is_string($class)) 
        {
            if ($this->has($class)) 
            {
                $component = $this->get($class);
            } 
            elseif ($this->hasModule($class))
            {
                $component = $this->getModule($class);
            } 
            elseif (strpos($class, ‘\\‘) === false) 
            {
                throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
            }
        }
        if (!isset($component)) 
        {
            $component = Yii::createObject($class);
        }
        // 如果这些组件实现了BootstrapInterface, 还会调用组件下的bootstrap函数
        if ($component instanceof BootstrapInterface) 
        {
            Yii::trace(‘Bootstrap with ‘ . get_class($component) . ‘::bootstrap()‘, __METHOD__);
            $component->bootstrap($this);
        } 
        else 
        {
            Yii::trace(‘Bootstrap with ‘ . get_class($component), __METHOD__);
        }
    }
}

3 run过程

整个run过程经历以下过程:

public function run()
{
    try {
        // 处理请求前
        $this->state = self::STATE_BEFORE_REQUEST;
        $this->trigger(self::EVENT_BEFORE_REQUEST);
        // 处理请求
        $this->state = self::STATE_HANDLING_REQUEST;
        $response = $this->handleRequest($this->getRequest());
        // 处理请求前
        $this->state = self::STATE_AFTER_REQUEST;
        $this->trigger(self::EVENT_AFTER_REQUEST);
        // 发送相应给客户端
        $this->state = self::STATE_SENDING_RESPONSE;
        $response->send();
        $this->state = self::STATE_END;
        return $response->exitStatus;
    } catch (ExitException $e) {
        $this->end($e->statusCode, isset($response) ? $response : null);
        return $e->statusCode;
    }
}

4 handleRequest

public function handleRequest($request)
{
    // 如果设置了catchAll变量, 那么所有请求都会跳转到这里
    // 示例:
    // 假设网站维护, 不希望有人访问到内容
    // 可以创建一个OfflineController控制器, 对应的views/offline/index.php可以写上
    // <h1>网站正在维护中</h1>
    // 然后在main.php中的$config中添加以下内容
    // ‘catchAll‘ => [ ‘offline/index‘]
    // 这样, 所有的访问都跳转到 网站正在维护中 的页面了

    if (empty($this->catchAll)) 
    {
        try 
        {
            list ($route, $params) = $request->resolve();
        } 
        catch (UrlNormalizerRedirectException $e) 
        {
            $url = $e->url;
            if (is_array($url)) 
            {
                if (isset($url[0])) 
                {
                    // ensure the route is absolute
                    $url[0] = ‘/‘ . ltrim($url[0], ‘/‘);
                }
                $url += $request->getQueryParams();
            }
            return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode);
        }
    } 
    // 跳转到catchAll指定的route
    else 
    {
        $route = $this->catchAll[0];
        $params = $this->catchAll;
        unset($params[0]);
    }
    try 
    {
        Yii::trace("Route requested: ‘$route‘", __METHOD__);
        $this->requestedRoute = $route;
        $result = $this->runAction($route, $params);
        ...
    }
    ...
}

5 runAction

创建Controller,并执行Controller对应的action

public function runAction($route, $params = [])
{
    // 创建Controller
    $parts = $this->createController($route);
    if (is_array($parts)) 
    {
        list($controller, $actionID) = $parts;
        $oldController = Yii::$app->controller;
        Yii::$app->controller = $controller;

        // 执行controller中的action
        $result = $controller->runAction($actionID, $params);
        if ($oldController !== null) 
        {
            Yii::$app->controller = $oldController;
        }
        return $result;
    } 
    else 
    {
        $id = $this->getUniqueId();
        throw new InvalidRouteException(‘Unable to resolve the request "‘ . ($id === ‘‘ ? $route : $id . ‘/‘ . $route) . ‘".‘);
    }
}
6 简述流程

通过Application创建app, 并且读入config, 装载扩展和组件
通过request解析被请求的路由
app根据路由创建controller
controller创建action
如果过滤器通过, 则会执行action
action会渲染视图view
view中的内容一般来自于model
渲染的结果通过response返回给客户端

 



以上是关于Yii2 分析运行流程的主要内容,如果未能解决你的问题,请参考以下文章

yii2源码分析之执行基本流程

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

yii2源码分析-概述

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Yii2片段缓存详解