Yii2 分析运行流程

简介: 版本创建Applicationrun过程handleRequestrunAction简述流程1 版本// yii\BaseYii\getVersionpublic static function getVersion(){ return '2.0.10';}2 创建Application// web/

1 版本

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

2 创建Application

// web/index.php

new yii\web\Application($config)

创建一个app用于处理本次请求

// 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返回给客户端
相关文章
|
3月前
|
缓存 测试技术 API
API的封装步骤流程
API封装流程是一个系统化的过程,旨在将内部功能转化为可复用的接口供外部调用。流程包括明确需求、设计接口、选择技术和工具、编写代码、测试、文档编写及部署维护。具体步骤为确定业务功能、数据来源;设计URL、请求方式、参数及响应格式;选择开发语言、框架和数据库技术;实现数据连接、业务逻辑、错误处理;进行功能、性能测试;编写详细文档;部署并持续维护。通过这些步骤,确保API稳定可靠,提高性能。
|
7月前
|
弹性计算 JSON Shell
基于Web API的自动化信息收集和整理
【4月更文挑战第30天】
90 0
支付系统---微信支付14----创建案例项目---介绍,第二步引入Swagger,接口文档和测试页面生成工具,定义统一结果的目的是让结果变得更加规范,以上就是谷粒项目的几个过程
支付系统---微信支付14----创建案例项目---介绍,第二步引入Swagger,接口文档和测试页面生成工具,定义统一结果的目的是让结果变得更加规范,以上就是谷粒项目的几个过程
|
JSON 数据格式 容器
SpringMVC运行流程分析之核心流程
SpringMVC运行流程分析之核心流程
35 0
|
7月前
|
API
工作流JBPM操作API删除流程&部署流程
工作流JBPM操作API删除流程&部署流程
50 0
|
7月前
|
移动开发 小程序 数据管理
9月开发者日回顾|小程序跳转接口等多个JSAPI更新,能力集成提供场景化排查工具
9月开发者日回顾|小程序跳转接口等多个JSAPI更新,能力集成提供场景化排查工具
65 0
|
存储
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)(三)
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)
336 0
|
XML Java 数据库
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)(一)
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)
335 0
|
数据处理 数据安全/隐私保护
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)(二)
Flowable:关于流程部署、启动、处理、完成各模块的浅析(图解)
463 0
|
前端开发 JavaScript 数据库
fastadmin框架-运行篇
fastadmin框架-运行篇
132 0