yii2 beta版 执行流程
yii2 beta版 执行流程
自动加载
1.composer的自动加载
//composer的加载实现了四种方式,可以看看
require(__DIR__ . '/../../vendor/autoload.php');
composer的自动加载只加载其下载的组件....和yii框架的加载没有任何关系 2.yii的加载
spl_autoload_register(['Yii', 'autoload'], true, true);
Yii::$classMap = include(__DIR__ . '/classes.php');
Yii::$container = new yii\di\Container;
这里使用spl_autoload_register把Yii::autoload注册成自动加载器,
- 判断在不在$classMap中,如果有别名获取别名的文件路径
- 如果不在$classMap中,则去除下划线,使用别名获取文件路径
- 引入该文件,并判断是不是类或者接口或者trait
public static function autoload($className)
{
if (isset(static::$classMap[$className])) {
$classFile = static::$classMap[$className];
if ($classFile[0] === '@') {
$classFile = static::getAlias($classFile);
}
} elseif (strpos($className, '\\') !== false) {
$classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);
if ($classFile === false || !is_file($classFile)) {
return;
}
} else {
return;
} include($classFile); if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) {
throw new UnknownClassException("Unable to find '$className' in file: $classFile. Namespace missing?");
}
}
Yii::$classMap中保存的是命名空间和文件实际路径的对应表,默认加载了所有yii提供的类 Yii::$container 实现了依赖注入, Yii::$app 继承serviceLocal..只实现了单例组件,其中属性_components保存的是对象,_definitions保存的是类,匿名函数或者对象
引导前初始化配置
1.检查配置中模块ID是不是存在
2.检查配置中basePath,vendorPath,runtimePath,timeZone是否存在,并设置
3.向配置中添加核心组件配置:
base:log,view,formatter,i18n,mailer,urlManager,assetManager,security
web:request,response,session,user,errorHandler
4.如果启用了YII_ENABLE_ERROR_HANDLER错误处理,则会注册错误处理组件.然后从配置中卸载errorHandler,避免之后的引导再次添加组件.
ini_set('display_errors', false); //注意这里...
set_exception_handler([$this, 'handleException']);
set_error_handler([$this, 'handleError']);
if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
}
register_shutdown_function([$this, 'handleFatalError']);
5.然后将配置中的值赋给applicaition
| 属性 | 说明 | 所在文件 |
| $_events | 使用on xxx 开通注册事件 | yii\base\Component |
| $_behaviors | 使用 as xxx开头注册行为 | yii\base\Component |
| $_components | 保存组件单例对象 | yii\di\ServiceLocator |
| $_definitions | 保存组件的原始数据 | yii\di\ServiceLocator |
| $params | 参数,是个数组 | yii\base\Module |
| $id | 模块ID | yii\base\Module |
| $module | 该模块的父模块 | yii\base\Module |
| $layout | 布局 | yii\base\Module |
| $controllerMap | 控制器地图 | yii\base\Module |
| $controllerNamespace | 控制器命名空间 | yii\base\Module |
| $defaultRoute | 默认路由 | yii\base\Module |
| $_basePath | 模块的根目录 | yii\base\Module |
| $_viewPath | 模块的视图目录 | yii\base\Module |
| $_layoutPath | 模块的布局目录 | yii\base\Module |
| $_modules | 子模块 | yii\base\Module |
| $_instances | 这个不常用,获取当前请求模块的实例 | yii\base\Module |
| $controllerNamespace | 'app\\controllers' | yii\base\Application |
| $name | 应用名称 | yii\base\Application |
| $version | 版本 | yii\base\Application |
| $charset | 字符编码.默认utf8 | yii\base\Application |
| $language | 语言,默认en-US | yii\base\Application |
| $sourceLanguage | 源语言 | yii\base\Application |
| $controller | 当前的控制器实例 | yii\base\Application |
| $layout | 布局 | yii\base\Application |
| $requestedRoute | 请求的路由 | yii\base\Application |
| $requestedAction | 请求的动作 | yii\base\Application |
| $requestedParams | 请求的参数 | yii\base\Application |
| $extensions | 扩展 | yii\base\Application |
| $bootstrap | 引导 | yii\base\Application |
| $state | 状态 | yii\base\Application |
| $defaultRoute | 默认路由 | yii\web\Application |
| $catchAll | 捕捉所有 | yii\web\Application |
| $controller | 当前控制器实例 | yii\web\Application |
引导阶段
- 1.初始化request组件
- 2.设置@webroot和@web别名
- 3.加载扩展extensions,如果没有设置extensions会读取@vendor/yiisoft/extensions.php中的扩展并设置别名,如果扩展可引导,则执行其bootstrap方法-----本身来讲扩展概念没什么用处,因为还是依靠modules来加载这些扩展
- 4.加载bootstrap中设置的组件和模块或者类,如果引导类实现了BootstrapInterface接口则执行bootstrap的方法
运行
- 触发请求前事件EVENT_BEFORE_REQUEST,yii-debug中注册了该事件
- 处理请求,如果catchAll不为空,则使用里面的路由.否则的话会解析获得路由和参数,
然后执行动作action,返回响应Response,或者响应的data数据.public function handleRequest($request)
{
if (empty($this->catchAll)) {
list ($route, $params) = $request->resolve();
} else {
$route = $this->catchAll[0];
$params = array_splice($this->catchAll, 1);
}
try {
Yii::trace("Route requested: '$route'", __METHOD__);
$this->requestedRoute = $route;
$result = $this->runAction($route, $params);
if ($result instanceof Response) {
return $result;
} else {
$response = $this->getResponse();
if ($result !== null) {
$response->data = $result;
} return $response;
}
} catch (InvalidRouteException $e) {
throw new NotFoundHttpException($e->getMessage(), $e->getCode(), $e);
}
} - 动作的执行:首先会根据路由创建控制器.然后执行动作.
public function runAction($route, $params = [])
{
$parts = $this->createController($route);
if (is_array($parts)) {
/* @var $controller Controller */
list($controller, $actionID) = $parts;
$oldController = Yii::$app->controller;
Yii::$app->controller = $controller;
$result = $controller->runAction($actionID, $params);
Yii::$app->controller = $oldController; return $result;
} else {
$id = $this->getUniqueId();
throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
}
}创建控制器
public function createController($route)
{
//路由为空则使用默认路由
if ($route === '') {
$route = $this->defaultRoute;
} // double slashes or leading/ending slashes may cause substr problem
$route = trim($route, '/');
if (strpos($route, '//') !== false) {
return false;
} //分解路由...前两个第一个可能是模块..第二个才是控制器
if (strpos($route, '/') !== false) {
list ($id, $route) = explode('/', $route, 2);
} else {
$id = $route;
$route = '';
} // module and controller map take precedence
$module = $this->getModule($id);
if ($module !== null) {
//如果有模块,则继续往下面找.这里是递归...能一直查询子模块
return $module->createController($route);
} //查看控制器地图...一般控制器地图里的控制器..作为产品临时使用的页面
if (isset($this->controllerMap[$id])) {
$controller = Yii::createObject($this->controllerMap[$id], [$id, $this]); return [$controller, $route];
} //执行到最后,没有子模块的时候...则将id加上剩余的路径(可能有多个/文件夹)
if (($pos = strrpos($route, '/')) !== false) {
$id .= '/' . substr($route, 0, $pos);
$route = substr($route, $pos + 1);
} $controller = $this->createControllerByID($id);
if ($controller === null && $route !== '') {
$controller = $this->createControllerByID($id . '/' . $route);
$route = '';
} return $controller === null ? false : [$controller, $route];
}获取模块
public function getModule($id, $load = true)
{
//这一段是获取子模块的..在运行中是没有作用的..这一小部分可以当方法使用..
if (($pos = strpos($id, '/')) !== false) {
// sub-module
$module = $this->getModule(substr($id, 0, $pos)); return $module === null ? null : $module->getModule(substr($id, $pos + 1), $load);
} //这是返回模块
if (isset($this->_modules[$id])) {
if ($this->_modules[$id] instanceof Module) {
return $this->_modules[$id];
} elseif ($load) {
Yii::trace("Loading module: $id", __METHOD__);
if (is_array($this->_modules[$id]) && !isset($this->_modules[$id]['class'])) {
$this->_modules[$id]['class'] = 'yii\base\Module';
}
/* @var $module Module */
$module = Yii::createObject($this->_modules[$id], [$id, $this]);
$module->setInstance($module);
return $this->_modules[$id] = $module;
}
} return null;
} - 触发请求后事件EVENT_AFTER_REQUEST,yii未注册事件
- 响应发送
yii2 beta版 执行流程的更多相关文章
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- Yii2 源码分析 入口文件执行流程
Yii2 源码分析 入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...
- [App Store Connect帮助]六、测试 Beta 版本(1)TestFlight Beta 版测试概述(iOS、Apple TVOS、watchOS)
TestFlight Beta 版测试让您可以分发您 App 的 Beta 版构建版本给测试员并收集反馈.您可以在您的 App Store Connect 帐户中一次为至多 100 个 App 启用 ...
- Ubuntu 安装yii2 advanced版 遇到的坑
1.安装 Composer https://www.yiichina.com/doc/guide/2.0/start-installation通过 Composer 安装 curl -sS https ...
- Mysql漂流系列(一):MySQL的执行流程
MySQL的执行流程 MySQL的执行流程: MySQL的执行流程分析: 1.当我们请求mysql服务器的时候,MySQL前端会有一个监听,请求到了之后,服务器得到相关的SQL语句,执行之前(虚线部分 ...
- yii2 advanced版基础部分
yii2 advanced版 一.目录结构 1.backend 和 frontend : 前后台入口,相当于是一个单独的Basic应用,有自己的 mvc 目录.配置文件目录.入口文件目录 2.cons ...
- Beta版测试报告
Beta版测试报告 测试中发现的Bug: Version 2.0 Bug List 1. 在动态监测界面,若随便点击“开始”.“关闭”.“结束”.红叉,会出现不定式崩溃现象. 2. 处理空数据时可能会 ...
- Dalvik虚拟机java方法执行流程和Method结构体分析
Method结构体是啥? 在Dalvik虚拟机内部,每个Java方法都有一个对应的Method结构体,虚拟机根据此结构体获取方法的所有信息. Method结构体是怎样定义的? 此结构体在不同的andr ...
- linux下无线鼠标驱动执行流程
操作系统: debian 7.4(linux 3.2.54) 硬件: 一个无线鼠标.一个有线鼠标.usb集线器. 从淘宝上花了15块钱买了个无线鼠标,很好奇它的驱动程序是如何执行的. 首先将usb集线 ...
随机推荐
- ContentProvider的那些小事(纯结论)
一.ContentProvider背景 Android系统是基于Linux系统内核来进行开发的,在Linux中,文件具有一系列的属性,其中最重要的莫过于文件权限了.关于文件权限,其实就是文件的读写,执 ...
- 给文件夹添加Everyone用户
DOC命令 C# code 1. cacls C:dming /g everyone:f /e /t 这样可以添加 2. cacls C:Program Files客友软件 /g everyone:f ...
- Linux下Anaconda的安装使用与卸载及问题解决
1. 安装 到官网下载对应的版本文件:Download Anaconda Now! 下载完之后,在终端输入: bash 下载好的文件 整个过程点几下回车就好了.但是到最后一步,会提示是否把anacon ...
- hadoop中OutputFormat 接口的设计与实现
OutputFormat 主要用于描述输出数据的格式,它能够将用户提供的 key/value 对写入特定格式的文件中. 本文将介绍 Hadoop 如何设计 OutputFormat 接口 , 以及一些 ...
- Windows10+Ubuntu双系统安装[
数据备份先别着急,你备份了吗?如果你看到这里,说明你选择了风险最大的一条路,在游戏开始之前,一定要做好数据备份,数据备份,数据备份. 创建磁盘分区 按住Win + X,选择“磁盘管理”: 磁盘管理概览 ...
- Android -- 写xml到SD卡中
信息类 private ...
- SVN-如何删除 SVN 文件夹下面的小图标
第一步:右键新建文本文件. 第二步:打开 并复制一下文件 到 新建文本文件. @echo on color 2f mode con: cols=80 lines=25 @REM ...
- Oracle中CBO优化器简介
Oracle中CBO优化器简介 Oracle数据库中的优化器是SQL分析和执行的优化工具.它负责制定SQL的执行计划,也就是它负责保证SQL的执行计划的效率最高,比如优化器决定Oracle以什么样的方 ...
- hdu 1087 简单dp
思路和2391一样的.. <span style="font-size:24px;">#include<stdio.h> #include<strin ...
- Python 创建包含列表的元组
“可变”的tuple前面我们看到了tuple一旦创建就不能修改.现在,我们来看一个“可变”的tuple:>>> t = ('a', 'b', ['A', 'B'])注意到 t 有 3 ...