thinkphp6.0 底层源码分析 - 类的自动加载、配置文件初始化

本文主要是介绍thinkphp6.0 底层源码分析 - 类的自动加载、配置文件初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

因为工作的需要,深入研究了一下thinkphp的源码,也算是对php知识的一个回归,工作这么多年,我一直坚信php是最好的Web编程语言,它可以做到成本和效率的一个平衡,知其然,更要知其所以然才是高手修炼之道

类的自动加载

不管是tp,yaf 还是yii ,所有的php框架都是从自动加载类库文件开始的,如果你不知道如何下手,就打开入口文件,从分析类的自动加载开始。

thinkphp6使用了composer去加载类库,整个composer的实现原理是:首先将各个使用了不同psr规范的类或映射类,以某种形式存储,然后当类找不到的时候,通过与存储的数据匹配,找到类所在的路径,然后去加载。

实际上composer总共有四种规范的文件需要加载,分别是:psr0、psr4、类映射、公共函数文件。

1.使用了单例模式,原理:简化后,psr0,psr4,classmap每个分类对应一个数组,类名在这三个数组进行检索,检索完成后,include

public static function getLoader()
{if (null !== self::$loader) {return self::$loader;}
}

2.此处先注册自动加载未定义类,紧跟着注销,是因为只加载并实例化classLoader类,其他类的加载,使用composer提供的方法,而不是自定义的。

spl_autoload_register(array('ComposerAutoloaderInit1283bda52466502421173f3a3bffb31b', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit1283bda52466502421173f3a3bffb31b', 'loadClassLoader'));

3.php版本大于5.6且未使用hhvm且没有启用zenGaurd加密扩展,即可使用静态加载,composer install 后,从各个vendor库的composer.json中读取autoload属性。

$useStaticLoader = PHP_VERSION_ID >= 50600 &&
!defined('HHVM_VERSION') &&
(!function_exists('zend_loader_file_encoded') ||
!zend_loader_file_encoded());

这里使用到了一个技巧,若对象类的成员属性是private,同时已经实现了set方法,现在需要实现同样的功能,直接复制给private成员属性。若是常用方法是将private属性变成public,或者修改set方法,或添加新的方法。但这里使用了系统类Closure的属性,可以通过bind方法,使用到了目标对象的private属性。

public static function getInitializer(ClassLoader $loader)
{return \Closure::bind(function () use ($loader) {$loader->prefixLengthsPsr4 = ComposerStaticInit1283bda52466502421173f3a3bffb31b::$prefixLengthsPsr4;$loader->prefixDirsPsr4 = ComposerStaticInit1283bda52466502421173f3a3bffb31b::$prefixDirsPsr4;$loader->fallbackDirsPsr0 = ComposerStaticInit1283bda52466502421173f3a3bffb31b::$fallbackDirsPsr0;$loader->classMap = ComposerStaticInit1283bda52466502421173f3a3bffb31b::$classMap;}, null, ClassLoader::class);
}

框架初始化执行流程

thinkphp6.0 应用的初始化做了大量的操作,其主要的操作有:加载环境变量、加载配置文件,加载语言包、监听 AppInit、initializers 数组包含的类的初始化。

public function run(Request $request = null): Response
{//初始化$this->initialize();//自动创建request对象$request = $request ?? $this->app->make('request', [], true);$this->app->instance('request', $request);try {$response = $this->runWithRequest($request);} catch (Throwable $e) {$this->reportException($e);$response = $this->renderException($request, $e);}return $response;
}

1.加载环境变量

重点强调一下在初始化加载initialize中,和底下的$this->lang->load$this->config->load都是一样的,都是加载对应文件中的数组。

// 加载环境变量
if (is_file($this->rootPath . '.env')) {$this->env->load($this->rootPath . '.env');
}object(think\Env)#8 (1) {["data":protected]=>array(14) {["APP_DEBUG"]=>string(4) "true"["DATABASE_CHARSET"]=>string(7) "utf8mb4"["PROJECT_WS_DOMAIN"]=>string(15) "wss://127.0.0.1"}
}

2.调试模式设置

t h i s − > d e b u g M o d e I n i t ( ) 运行原理详见注释 , 需要注意的是,这里不知道是不是源码中的 B u g , ! this->debugModeInit() 运行原理详见注释,需要注意的是,这里不知道是不是源码中的Bug,! this>debugModeInit()运行原理详见注释,需要注意的是,这里不知道是不是源码中的Bug!this->appDebug 恒为true (有时间在做ob缓存和依赖注入的知识点)。

protected function debugModeInit(): void
{// 应用调试模式if (!$this->appDebug) {$this->appDebug = $this->env->get('app_debug') ? true : false;// 关闭错误显示ini_set('display_errors', 'Off');}// 如果不是命令行模式if (!$this->runningInConsole()) {// 重新申请一块比较大的bufferif (ob_get_level() > 0) {// 相当于ob_get_contents() 和 ob_clean()// 获取缓冲区内容并删除缓冲区内容$output = ob_get_clean();}// 开启新的缓冲区控制ob_start();if (!empty($output)) {// 由于开启了新的缓冲区控制,// 这里不会直接输出$output// 而是等到依次执行了ob_flush()和flash()之后才将内容输出到浏览器echo $output;}}
}
  1. 加载应用文件和配置等操作

在加载全局初始化文件的时候,加载是有顺序的,首先加载app目录下的common.php文件和系统下的helper.php文件,然后加载config目录下的所有php文件,最后加载event事件和service服务文件。

protected function load(): void
{$appPath = $this->getAppPath();# 首先加载app目录下的common.php文件和系统下的helper.php文件if (is_file($appPath . 'common.php')) {include_once $appPath . 'common.php';}include_once $this->thinkPath . 'helper.php';$configPath = $this->getConfigPath();$files = [];if (is_dir($configPath)) {$files = glob($configPath . '*' . $this->configExt);}foreach ($files as $file) {$this->config->load($file, pathinfo($file, PATHINFO_FILENAME));}# 然后加载config目录下的所有php文件# 最后加载event事件和service服务文件if (is_file($appPath . 'event.php')) {$this->loadEvent(include $appPath . 'event.php');}if (is_file($appPath . 'service.php')) {$services = include $appPath . 'service.php';foreach ($services as $service) {$this->register($service);}}}

4.初始化错误和异常处理、注册系统服务和初始化系统服务

最后,初始化错误和异常处理、注册系统服务和初始化系统服务,这几行代码做了比较多的操作:分别实例化包含在里面的类,然后调用其init方法。initializers 数组的值如下:

 // 初始化
foreach ($this->initializers as $initializer) {$this->make($initializer)->init($this);
}
protected $initializers = [Error::class,RegisterService::class,BootService::class,
];

结尾

thinkphp6.0的类的自动加载和初始化就介绍到这里了,知其然,更要知其所以然才是高手修炼之道。

这篇关于thinkphp6.0 底层源码分析 - 类的自动加载、配置文件初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/336563

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给