写在前面,写这些随笔是记录下自己看Yii2源码的过程,可能会有些流水账,大部分解析放在注释里说明,由于个人水平有限,有不正确的地方还望斧正。

web入口文件Index.php

// 定义全局的常量,YII_DEBUG标识是够开启debug模式,YII_ENV标识出当前运行环境,默认env(开发), 上线后改成prod来表示正式环境。
defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); // 加载composer vendor的autoload文件
require(__DIR__ . '/../vendor/autoload.php');
// 加载Yii框架
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

入口文件很简单,做了一些初始化工作,具体看注释。

接下来看加载的Yii文件代码:

<?php
/**
* Yii bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/ require(__DIR__ . '/BaseYii.php'); /**
* Yii is a helper class serving common framework functionalities.
*
* It extends from [[\yii\BaseYii]] which provides the actual implementation.
* By writing your own Yii class, you can customize some functionalities of [[\yii\BaseYii]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Yii extends \yii\BaseYii
{
}
// 调用Yii::autoload来注册autoload, 而且是放到autoload队列之首。
spl_autoload_register(['Yii', 'autoload'], true, true);
// 包含class映射文件
Yii::$classMap = require(__DIR__ . '/classes.php');
// 初始化DI容器
Yii::$container = new yii\di\Container();

PS:这边涉及到php的自动加载概念(https://www.php.net/manual/zh/function.spl-autoload-register)和设计模式-依赖注入。

这个文件主要进行一些YII源码的初始化操作,这里的class Yii只是继承了BaseYii,没有写任何代码,所以yii2的源码都是在BaseYii里面的,这里留空是为了给使用者自定义的。

注册自动加载

public static function autoload($className)
{
// 从classMap里寻找
if (isset(static::$classMap[$className])) {
$classFile = static::$classMap[$className];
if ($classFile[0] === '@') {
$classFile = static::getAlias($classFile);
}
} elseif (strpos($className, '\\') !== false) {
// 命名空间访问,先把命名空间的格式转成路径别名,例如: yii\base\Component 转成 @yii/base/Component.php
$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?");
}
}

​ 简单总结下,这个函数规定了一些规则让php在寻找未知class时候可以include对应的文件,规则如下:

​ (1) 在classMap里面找

​ (2)如果class是使用命名空间访问的(例如:yii\base\Component), 会按照@yii/base/Component.php这样的路径去加载。

规则1

规则1说从classMap里面,那么classMap是什么呢,在入口文件里能找到Yii::$classMap = require(__DIR__ . '/classes.php');,然后去看下classes.php是什么样子的:

return [
'yii\base\Action' => YII2_PATH . '/base/Action.php',
'yii\base\ActionEvent' => YII2_PATH . '/base/ActionEvent.php',
.....
]

只是返回一个数组,key是class的名字,value是对应php文件的路径(YII2_PATH是预定于的常量,表示当前目录)。

if (isset(static::$classMap[$className])) {

所以Yii::autoload会先判断是否在classMap里面。

规则2(命名空间)

$classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);

函数会先把命名空间形式的调用转成对应的路径别名,再用getAlias函数转成对应的路径。

路径别名

再来看看static::getAlias()这个函数是怎么把路径别名转成路径的。

public static $aliases = ['@yii' => __DIR__]; // 预设的路径别名映射数组
public static function getAlias($alias, $throwException = true)
{
// 检查是否有@前缀,没有的话直接返回。
if (strncmp($alias, '@', 1)) {
// not an alias
return $alias;
}
// 取出@alias部分赋值给root
$pos = strpos($alias, '/');
$root = $pos === false ? $alias : substr($alias, 0, $pos);
// 检查root是否在$aliases里是否有对应的alias
if (isset(static::$aliases[$root])) {
// 在$aliases里找到对应的@alias然后转化成实际的路径并返回
if (is_string(static::$aliases[$root])) {
return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
}
// 如果找到的不是对应的路径字符串,就变量这个数组,看看里面有没有对应的
foreach (static::$aliases[$root] as $name => $path) {
if (strpos($alias . '/', $name . '/') === 0) {
return $path . substr($alias, strlen($name));
}
}
} if ($throwException) {
throw new InvalidParamException("Invalid path alias: $alias");
} return false;
}

创建Web应用实例

$config = require(__DIR__ . '/../config/web.php'); // 加载配置文件
(new yii\web\Application($config))->run();

到这里就开始涉及config配置的解析了,下一篇才慢慢分析。

最新文章

  1. 0.Win8.1,Win10,Windows Server 2012 安装 Net Framework 3.5
  2. SVN和Git下载地址
  3. 6to5 – 让你即刻体验 ECMAScript 6 编程
  4. nmap的script参数列表
  5. 从一个例子中体会React的基本面
  6. 数据结构复习:交换排序原理及C++实现
  7. 滑动菜单栏开源项目SlidingMenu的使用
  8. pl/sql developer 中文字段显示乱码
  9. asp发布至IIS
  10. JAVA学习笔记--二
  11. Memcached简明介绍
  12. php 分页类(2)
  13. sql关键字之null
  14. mysql案例~mysql主从复制延迟概总
  15. 2019/4/2 wen 多态、抽象
  16. CSS 初知
  17. Mysql模糊查询 select count(*) from sys_invitation where from_id like &#39;%1006%&#39;;
  18. 音视频处理之FFmpeg+SDL视频播放器20180409
  19. quote函数什么意思,怎么用
  20. librec库

热门文章

  1. Burpsuite intruder模块 越过token进行爆破,包含靶场搭建
  2. 案例:DG主库未设置force logging导致备库坏块
  3. 在k8s上部署日志系统elfk
  4. win10系统下office 2019激活
  5. Alink漫谈(七) : 如何划分训练数据集和测试数据集
  6. Tftp文件传输服务器(基于UDP协议)
  7. C# 9.0 新特性之模式匹配简化
  8. os:获取当前目录路径,上级目录路径,上上级目录路径
  9. 让人又爱又恨的Lombok,到底该不该用
  10. 030.Kubernetes核心组件-Scheduler