浅谈 thinkphp composer 扩展包加载原理
浅谈 thinkphp composer 扩展包加载原理
本文将介绍 ThinkPHP 中 Composer 扩展包的加载原理,帮助读者更好地理解和应用该功能。
前言
如题,今天感觉好久没有更新博客了。最近迷上了物联网开发。一直在研究stm32、51这些东西。想起来前几天群里面有人问到tp扩展包原理。其实这个前几年也就研究过。网上搜了搜发现相关文章也很少(也有可能是我搜索姿势不对)今天就来写一篇thinkphp composer包加载原理
概览
- 当进行
composer update或者composer require操作时。则会执行service:discover这个命令。把当前所有已经加载的库信息都进行一次匹配。如果匹配到了think关键字的services属性。则把服务类输出成配置文件到vendor/services.php文件中 - 当一次应用初始化(通常为一次访问开始时).则会引入
vendor/services.php中的service服务类到当前应用内进行初始化
源码解析
composer包加载流程文字详解 建议先阅读一下这篇前两年我写的文章 Thinkphp6源码解析之分析 路由篇-请求流程
在第三步进入到Http->runWithRequest这个方法中后。可以看到又调用了initialize方法

追进这个方法可以看到

追进initialize方法看实现
/**
* 初始化应用
* @access public
* @return $this
*/
public function initialize()
{
// 设置当前初始化状态
$this->initialized = true;
// 设置应用开始时间
$this->beginTime = microtime(true);
// 获取到php的内存
$this->beginMem = memory_get_usage();
// 加载环境变量 例如当前应用目录下的 .env文件
$this->loadEnv($this->envName);
// 设置配置文件后缀
$this->configExt = $this->env->get('config_ext', '.php');
// 调试模式设置
$this->debugModeInit();
// 加载全局初始化文件
$this->load();
// 加载应用默认语言包
$this->loadLangPack();
// 监听AppInit
$this->event->trigger(AppInit::class);
// 设置php默认时区
date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));
// 初始化当前系统配置的默认服务
foreach ($this->initializers as $initializer) {
// 调用make函数生成对象。并且执行对象中的init方法
$this->make($initializer)->init($this);
}
return $this;
}
重点是初始化当前系统配置的默认服务这个$this->make($initializer)->init($this)函数,看看initializers属性
/**
* 应用初始化器
* @var array
*/
protected $initializers = [
Error::class,
RegisterService::class,
BootService::class,
];
追到这里就是关键了。上面把这里面的类进行初始化。并且执行类中的init方法。直接看RegisterService::class类的init方法
public function init(App $app)
{
// 获取当前项目根目录。拼接上 vendor/services.php
$file = $app->getRootPath() . 'vendor/services.php';
$services = $this->services;
if (is_file($file)) {
$services = array_merge($services, include $file);
}
// 初始化services
foreach ($services as $service) {
if (class_exists($service)) {
$app->register($service);
}
}
}
读到这里的可以看看自己项目vendor目录下是不是有一个services.php,接下来讲一讲composer.json这个文件
在tp框架中的composer.json有这样一个配置

这里这个概念我直接让chatgpt来解读。解读内容如下

接下来直接看service:discover这个命令。追到vendor\topthink\framework\src\think\console\command\ServiceDiscover.php文件
public function execute(Input $input, Output $output)
{
// 获取到当前项目根目录下的 vendor/composer/installed.json 文件
if (is_file($path = $this->app->getRootPath() . 'vendor/composer/installed.json')) {
// json解析
$packages = json_decode(@file_get_contents($path), true);
// Compatibility with Composer 2.0
if (isset($packages['packages'])) {
$packages = $packages['packages'];
}
$services = [];
foreach ($packages as $package) {
// 判断当前包是否在extra字段里面声明了think关键字中的services属性。如果声明了就把services给装载到services变量内
if (!empty($package['extra']['think']['services'])) {
$services = array_merge($services, (array) $package['extra']['think']['services']);
}
}
$header = '// This file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL . 'declare (strict_types = 1);' . PHP_EOL;
// 用var_export函数把services变量打印成可读性代码。并且写入到根目录vendor目录下的services
$content = '<?php ' . PHP_EOL . $header . "return " . var_export($services, true) . ';';
file_put_contents($this->app->getRootPath() . 'vendor/services.php', $content);
$output->writeln('<info>Succeed!</info>');
}
一直到这就算结束了
写在最后
如果觉得这篇文章对你有帮助。不妨点个赞留个关注再走
浅谈 thinkphp composer 扩展包加载原理的更多相关文章
- 深入解析 composer 的自动加载原理 (转)
深入解析 composer 的自动加载原理 转自:https://segmentfault.com/a/1190000014948542 前言 PHP 自5.3的版本之后,已经重焕新生,命名空间.性状 ...
- composer 实现自动加载原理
简介 一般在框架中都会用到composer工具,用它来管理依赖.其中composer有类的自动加载机制,可以加载composer下载的库中的所有的类文件.那么composer的自动加载机制是怎么实现的 ...
- 【原】从一个bug浅谈YUI3组件的资源加载
篇前声明:为了不涉及业务细节,篇内信息统一以某游戏,某功能代替 前不久,某游戏准备内测客户端,开发人员测试过程中发现某功能突然不灵了,之前的测试一切ok,没有发现任何异常,第一反应是,游戏内浏览器都是 ...
- 深入解析 composer 的自动加载原理
PHP 自5.3的版本之后,已经重焕新生,命名空间.性状(trait).闭包.接口.PSR 规范.以及 composer 的出现已经让 PHP 变成了一门现代化的脚本语言.PHP 的生态系统也一直在演 ...
- laravel框架应用和composer扩展包开发
laravel5.5+ laravel官方地址 laravel是目前最流行的php框架,发展势头迅猛,应用非常广泛,有丰富的扩展包可以应付你能想到的各种应用场景,laravel框架思想前卫,跟随时代潮 ...
- 使用PSR-4配合composer autoload 自动加载文件夹
require 文件很麻烦,使用PSR-4搭配composer一次加载,终生受用. 感觉类似java中的import了,自己先记录一下最近理解的. 用composer管理自己的包吧 安装compose ...
- laravel composer 扩展包开发(超详细)
laravel composer 扩展包开发(超详细) 置顶 2018年02月05日 11:09:16 Simael__Aex 阅读数:10396 版权声明:转载请注明出处:http://blo ...
- 详解composer的自动加载机制
composer是一个用PHP开发的用来管理项目依赖的工具,当你在项目中声明了依赖关系后,composer可以自动帮你下载和安装这些依赖库,并实现自动加载代码. 安装composer composer ...
- java 启动查看jar包加载顺序并设置classpath
本文为博主原创,转载请注明出处: 1.idea查看jar包加载顺序 jdk8 可以通过 -XX:+TraceClassPaths 参数进行查看jar包的加载顺序 jdk11 可以通过 ...
- thinkphp pathinfo nginx 无法加载模块:Index
thinkphp 报了 无法加载模块:Index 错误位置 FILE: /var/multrix/wxactivity_archive/ThinkPHP/Library/Think/Dispatche ...
随机推荐
- C#自定义事件(简单版本)
C#中的事件分为两种:一种是厂商微软在VS中已经内置,以供用户使用:另一种是有用户自己定义的事件: 先简单回顾下第一种: [场景1]一个Form上一个Textbox控件和Button控件,当用户按下B ...
- IBM Cloud Computing Practitioners 2019 (IBM云计算从业者2019)Exam答案
Cloud Computing Practitioners 2019 IBM Cloud Computing Practitioners 2019 (IBM云计算从业者2019)Exam答案,加粗的为 ...
- flak_login用法
基础的信息和全局配置这里就不多说,需要用到再斟酌也可以的.这里也是针对每个模块较为常用的进行解释说明,后期再使用过程中遇到会进行补充. Login_Manager LoginManager是一个类,有 ...
- 详解事务模式和Lua脚本,带你吃透Redis 事务
摘要:Redis事务包含两种模式:事务模式和Lua脚本. 本文分享自华为云社区<一文讲透 Redis 事务>,作者: 勇哥java实战分享. 准确的讲,Redis事务包含两种模式:事务模式 ...
- day107:MoFang:Python操作MongoDB数据库:PyMongo
目录 PyMongo 1.PyMongo安装 2.数据库连接 3.数据库管理 4.集合管理 5.文档管理 PyMongo 1.PyMongo安装 pip install pymongo 2.数据库连接 ...
- 升级:In-Place Upgrade升级MySQL5.6.26
升级需谨慎,事前先备份 MySQL升级的实质是对数据字典的升级,数据字典有:sys.mysql.information_schema.performance_schema . MySQL升级的两种方式 ...
- 【SSM项目】尚筹网(二)基于Servlet3.0项目搭建:日志系统以及声明式事务
1 日志系统 常见的日志系统实现log4j.JUL(jdk自带).log4j2.logback(和SLF4J同一个作者,能够天然衔接),这些实现就类似于java的接口实现,而SLF4J就类似于java ...
- 如何生成文本: 通过 Transformers 用不同的解码方法生成文本
简介 近年来,随着以 OpenAI GPT2 模型 为代表的基于数百万网页数据训练的大型 Transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注.开放域中的条件语言生成效果令人 ...
- Win Pycharm + Airtest + 夜神模拟器 实现APP自动化
前言: 前面已经讲过了Airtest的简单配置与使用了,相信大家已经对于操作Airtest没有什么问题了(#^.^#) 但是在Airtest IDE中编写代码是有局限性的,而且不能封装Airtest的 ...
- 突破tls/ja3新轮子
我之前的文章介绍了SSL指纹识别 https://mp.weixin.qq.com/s/BvotXrFXwYvGWpqHKoj3uQ 很多人来问我BYPass的方法 主流的BYPASS方法有两大类: ...