Yii2源码分析(一):入口
写在前面,写这些随笔是记录下自己看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配置的解析了,下一篇才慢慢分析。
Yii2源码分析(一):入口的更多相关文章
- Yii2 源码分析 入口文件执行流程
Yii2 源码分析 入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...
- CodeIgniter框架——源码分析之入口文件index.php
CodeIgniter框架的入口文件主要是配置开发环境,定义目录常量,加载CI的核心类core/CodeIgniter.php. 在index.php中,CI首先做的事情就是设置PHP的错误报告, ...
- jQuery 源码分析(二) 入口模块
jQuery返回的对象本质上是一个JavaScript对象,而入口模块则可以保存对应的节点的引用,然后供其它模块操作 我们创建jQuery对象时可以给jQuery传递各种不同的选择器,如下: fals ...
- twemproxy源码分析1——入口函数及启动过程
最近工作中需要写一个一致性哈希的代理,在网上找到了twemproxy,结合网上资料先学习一下源码. 一.Twemproxy简介 Twemproxy是memcache与redis的代理,由twitter ...
- yii2 源码分析1从入口开始
我是在 backend 一步步打印的 很多地方我也是很模糊 .后来发现一位大神的文章(http://www.yiichina.com/tutorial/773) 参考文章自己动手开始写的 至于后来的 ...
- yii2 源码分析 object类分析 (一)
转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6737327.html yii2基本上所有的类都是继承的object类,下面就来分析一下object类吧 obje ...
- yii2 源码分析 model类分析 (五)
模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...
- yii2 源码分析Action类分析 (六)
Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方 ...
- yii2 源码分析Behavior类分析 (四)
Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要 ...
随机推荐
- SpringCloud+Ehcache
1.pom文件引入 <!-- https://mvnrepository.com/artifact/org.ehcache/ehcache --><dependency>< ...
- ASP.NET Core 3.1 WebApi部署到腾讯云CentOS 7+Docker
一.准备 首先需要有一台CentOS服务器,安装最新版Docker,配置镜像加速等,安装方法网上很多,下面是一些相关指令: yum install -y yum-utils device-mapper ...
- 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...
- kernel list 实践
list.h /******* 链表实现,来自内核 **************************************************/ /** * container_of - c ...
- TensorFlow从0到1之TensorFlow优化器(13)
高中数学学过,函数在一阶导数为零的地方达到其最大值和最小值.梯度下降算法基于相同的原理,即调整系数(权重和偏置)使损失函数的梯度下降. 在回归中,使用梯度下降来优化损失函数并获得系数.本节将介绍如何使 ...
- JVM 之 Linux定位CPU过高问题及优化
项目部署以后出行卡顿现象,所以对问题进行了排查,记录一下排查过程 (从CSDN编辑器贴过来的,图有水印) 1.找进程 top 可以发现,是Java进程导致的CPU过高,致使系统卡顿 2.找线程 ps ...
- WPF入门(2)——依赖属性
今天我们说说依赖属性 什么是依赖属性? 当然,学术定义依旧Please Baidu:https://baike.baidu.com/item/%E4%BE%9D%E8%B5%96%E5%B1%9E%E ...
- Spring整合JDBC temple
一.Spring对Jdbc的支持 Spring为了提供对Jdbc的支持,在Jdbc API的基础上封装了一套实现,以此建立一个 JDBC 存取框架. 作为 Spring JDBC 框架的核心, JDB ...
- Ubuntu16.06常见服务搭建
摘要 系统环境Ubuntu 16.04 amd64 隔一段时间要配一次服务记不住,记录在这里方便以后安装. 目前更新了以下服务: ssh samba vimrc // 20200126更新 ssh 安 ...
- 深入浅出Transformer
Transformer Transformer是NLP的颠覆者,它创造性地用非序列模型来处理序列化的数据,而且还获得了大成功.更重要的是,NLP真的可以"深度"学习了,各种基于tr ...