Yii2 源码分析 入口文件执行流程
Yii2 源码分析 入口文件执行流程
1. 入口文件:web/index.php,第12行。(new yii\web\Application($config)->run())
入口文件主要做4件事:
1. 设置环境
2. 加载自动加载
3. 引入Web需要的配置
4. 运行应用Application
1 <?php
2
3 // comment out the following two lines when deployed to production
4 defined('YII_DEBUG') or define('YII_DEBUG', true);
5 defined('YII_ENV') or define('YII_ENV', 'dev');
6
7 require __DIR__ . '/../vendor/autoload.php';
8 require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
9
10 $config = require __DIR__ . '/../config/web.php';
11
12 (new yii\web\Application($config))->run();
2. 接下来看运行应用Application做了哪些事情
1. 执行应用类的构造方法:__construct()
a. 设置全局应用对象:Yii::$app
b. 加载配置,检查配置是否正常配置并设置全局配置参数:如,检查应用id是否设置,检查basePath是否设置,检查缓存目录...,并设置对应的应用属性参数
c. 注册全局错误异常处理机制
d. 设置配置中对应对象的属性
189 /**
190 * Constructor.
191 * @param array $config name-value pairs that will be used to initialize the object properties.
192 * Note that the configuration must contain both [[id]] and [[basePath]].
193 * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
194 */
195 public function __construct($config = [])
196 {
197 Yii::$app = $this;
198 static::setInstance($this);
199
200 $this->state = self::STATE_BEGIN;
201
202 $this->preInit($config);
203
204 $this->registerErrorHandler($config);
205
206 Component::__construct($config);
207 }
2. 执行init()方法,执行引导:bootstrap
a. 注册Yii扩展的组件,组件目录位于:根目录\vendor\yiisoft\extension/php
b. 注册用户自定义配置文件main.php中属性boostrap配置的容器配置
267 /**
268 * {@inheritdoc}
269 */
270 public function init()
271 {
272 $this->state = self::STATE_INIT;
273 $this->bootstrap();
274 }
3. 执行run()方法,执行应用请求流程,Yii处理请求逻辑应用的方法入口,应用的生命周期及对应的行为、事件处理函数等入口
374 /**
375 * Runs the application.
376 * This is the main entrance of an application.
377 * @return int the exit status (0 means normal, non-zero values mean abnormal)
378 */
379 public function run()
380 {
381 try {
382 $this->state = self::STATE_BEFORE_REQUEST;
383 $this->trigger(self::EVENT_BEFORE_REQUEST);
384
385 $this->state = self::STATE_HANDLING_REQUEST;
386 $response = $this->handleRequest($this->getRequest());
387
388 $this->state = self::STATE_AFTER_REQUEST;
389 $this->trigger(self::EVENT_AFTER_REQUEST);
390
391 $this->state = self::STATE_SENDING_RESPONSE;
392 $response->send();
393
394 $this->state = self::STATE_END;
395
396 return $response->exitStatus;
397 } catch (ExitException $e) {
398 $this->end($e->statusCode, isset($response) ? $response : null);
399 return $e->statusCode;
400 }
401 }
解析Yii执行run()的生命周期,在这个方法中可以看到有一些$this->state变量设置,这个变量主要用来记载Yii应用请求处于每个阶段的处理过程,例如上面的__construct(),init(),以及run()都相应的设置了Yii全局应用请求的状态
其中有:STATE_BEGIN(应用实例化阶段)、STATE_INIT(执行init方法初始化阶段)、STATE_BEFORE_REQUEST(执行请求前阶段)、STATE_HANDLING_REQUEST(处理请求中阶段)、STATE_AFTER_REQUEST(执行请求后阶段)、STATE_SENDING_RESPONSE(返回响应阶段)、STATE_END(应用结束输出阶段)
这里主要来分析run()方法中第385行:$response = $this->handleRequest($this->getRequest()); 处理请求中阶段:
1. 获取请求并传递给handRequest处理请求方法,handleRequest方法位于:\vendor\yiisoft\yii2\web\Application文件中
2. Application文件第80-99行,解析请求URL地址,获取请求路径,地址参数:82行 list($route, $params) = $request->resolve();
3. Application文件第100-116行,根据请求路径及参数,创建路径指向的路由控制器文件,执行方法并传入参数:103行 $result = $this->runAction($route, $params);
a. \vendor\yiisoft\yii2\base\Module::runAction($route, $params),找到路由文件地址:522行 $parts = $this->createController($route)
b. 分析路由控制器,及请求方法:list($controller, $actionID) = $parts
c. 设置全局控制器
d. 执行控制器中的方法体并传入参数:528行 $result = $controller->runAction($actionID, $params)
I. \vendor\yiisoft\yii2\base\Controller::runAction($id, $params = []),第126-138行,方法体创建过程
i. 创建方法体对象:创建方法体对象 第219行 createAction($id)
ii. 正则匹配请求方法名是否符合规范
iii. 方法名转化,以'-'切割,转换大小写
iiii. 为方法名添加'action'前缀
iiiii. 验证该方法名是否存在该类中
iiiiii. 检查该方法是否属于公共方法
iiiiiii. 执行方法体前
II. 执行模块前置行为(全局行为处理)
III. 执行方法体前置行为(这里可验证方法权限、参数、跨域等行为)
IIII. 执行方法体【业务逻辑,这里就是我们编写代码逻辑controller::action】
IIIII. 执行方法体后置行为(这里可对返回数据进行验证处理)
IIIIII. 执行模块后置行为(全局行为处理)
IIIIIII. 获取以上执行方法体以及模块行为事件处理的最终结果并返回:第172行
这里分析下Yii怎么解析路由文件,执行路径:web\Application::handleRequest->runAction()103行 => base\Module::runAction->createController()522行 =>base\Module::createController()562行:
1. 解析地址,以'/'切割,根据route路由地址解析出id模块以及操作控制器路由地址route 第564-579行
2. 加载模块id对应的模块配置 第582-589行
3. 根据控制器路由地址,加载控制器文件 第591-602行,主要代码:$controller = $this->createControllerByID($id . '/', $route) 598行
a. 检查类文件及类前缀路径是否符合规范 vendor\yiisoft\base\Module::629行
b. 加载模块完,加载控制器,检查类文件是否存在,控制器地址文件不存在则报错404
c. 加载容器的时候,自动给方法加上controller vendor\yiisoft\base\Module.php::635行
d. 匹配正确的文件,实例化控制器 vendor\yiisoft\base\Module.php::642行
4. 返回对应的类实例化及操作方法到执行前创建控制器 vendor\yiisoft\yii2\base\Module::522行
5. 检查返回是否符合数组(控制器实例及操作方法),否:页面找不到
6. 设置App应用全局控制器 vendor\yiisoft\yii2\base\Module::527行
7. 传递参数到控制器并执行控制器方法 vendor\yiisoft\yii2\base\Module::528行
Yii2 源码分析 入口文件执行流程的更多相关文章
- asyncio源码分析之基本执行流程
基于async关键字的原生协程 # 定义一个简单的原生协程cor async def cor(): print('enter cor') print('exit cor') print(type(co ...
- mybatis(五):源码分析 - mapper文件解析流程
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- (转)linux内存源码分析 - 内存回收(整体流程)
http://www.cnblogs.com/tolimit/p/5435068.html------------linux内存源码分析 - 内存回收(整体流程) 概述 当linux系统内存压力就大时 ...
- JVM源码分析之JVM启动流程
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十四篇. 今天呢!灯塔君跟大家讲: JVM源码分析之JVM启动流程 前言: 执行Java类的main方法,程序就能运 ...
- Solr4.8.0源码分析(5)之查询流程分析总述
Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...
- HDFS源码分析DataXceiver之整体流程
在<HDFS源码分析之DataXceiverServer>一文中,我们了解到在DataNode中,有一个后台工作的线程DataXceiverServer.它被用于接收来自客户端或其他数据节 ...
- Yii2源码分析(一):入口
写在前面,写这些随笔是记录下自己看Yii2源码的过程,可能会有些流水账,大部分解析放在注释里说明,由于个人水平有限,有不正确的地方还望斧正. web入口文件Index.php // 定义全局的常量,Y ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
随机推荐
- 使用cerebro可视化ElasticSearch集群信息
使用cerebro可视化ElasticSearch集群信息 一.背景 二.安装步骤 1.下载并解压 2.配置cerebro 3.启动 cerebro 4.启动界面 三.注意事项 四.参考文档 一.背景 ...
- Noip模拟17 2021.7.16
我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...
- 集合先从ArrayList开始
本篇文章非常建议直接从经典Demo开始哦~ 一.ArrayList简介 ArrayList 的底层是数组队列,相当于动态数组.与 Java 中的数组相比,它的容量能动态增长.在添加大量元素前,应用程序 ...
- Linux文件IO操作
来源:微信公众号「编程学习基地」 目录 文件操作 Linux文件类型 Linux文件权限 修改文件权限 Linux error 获取系统调用时的错误描述 打印错误信息 系统IO函数 open/clos ...
- 个人宽带如何开启IPv6网络访问
IPv6是大势所趋,就在前段时间湖南联通发布公告,对家庭宽带提供 IPv6 地址,不再提供 IPv4地址,那本文就介绍 个人宽带如何开启 IPv6网络访问. 湖南联通停止向普通家庭宽带用户提供公网 I ...
- 『学了就忘』Linux基础 — 13、Linux系统的分区和格式化
目录 1.Linux系统的分区 (1)磁盘分区定义 (2)两种分区表形式 (3)MBR分区类型 2.Linux系统的格式化 (1)格式化定义 (2)格式化说明 1.Linux系统的分区 (1)磁盘分区 ...
- SprinMvc快速入门
1.spring mvc Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架. 查看官方文档:https://docs.spring.io/sp ...
- 这一次,解决Flutter Dialog的各种痛点!
前言 Q:你一生中闻过最臭的东西,是什么? A:我那早已腐烂的梦. 兄弟萌!!!我又来了! 这次,我能自信的对大家说:我终于给大家带了一个,能真正帮助大家解决诸多坑比场景的pub包! 将之前的flut ...
- Latex使用CJK包添加字体
最近写论文时有个中文期刊提供的LaTeX模板使用CJK宏包,大致是这样的: \documentclass{article} \usepackage{CJK} \begin{document} \beg ...
- UVA1104 Chips Challenge
一.题目 有一个 \(n\times n\) 的矩阵,每个元素可能是 ..C./ 的其中一种,分别表示可以放置芯片.已经放置了芯片.不能放置芯片,你可以分别决定是否可以放置芯片的位置放置芯片. 最后需 ...