浅谈 thinkphp composer 扩展包加载原理

本文将介绍 ThinkPHP 中 Composer 扩展包的加载原理,帮助读者更好地理解和应用该功能。


前言


如题,今天感觉好久没有更新博客了。最近迷上了物联网开发。一直在研究stm32、51这些东西。想起来前几天群里面有人问到tp扩展包原理。其实这个前几年也就研究过。网上搜了搜发现相关文章也很少(也有可能是我搜索姿势不对)今天就来写一篇thinkphp composer包加载原理


概览


  1. 当进行 composer update 或者 composer require 操作时。则会执行service:discover这个命令。把当前所有已经加载的库信息都进行一次匹配。如果匹配到了think关键字的services属性。则把服务类输出成配置文件到vendor/services.php文件中
  2. 当一次应用初始化(通常为一次访问开始时).则会引入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 扩展包加载原理的更多相关文章

  1. 深入解析 composer 的自动加载原理 (转)

    深入解析 composer 的自动加载原理 转自:https://segmentfault.com/a/1190000014948542 前言 PHP 自5.3的版本之后,已经重焕新生,命名空间.性状 ...

  2. composer 实现自动加载原理

    简介 一般在框架中都会用到composer工具,用它来管理依赖.其中composer有类的自动加载机制,可以加载composer下载的库中的所有的类文件.那么composer的自动加载机制是怎么实现的 ...

  3. 【原】从一个bug浅谈YUI3组件的资源加载

    篇前声明:为了不涉及业务细节,篇内信息统一以某游戏,某功能代替 前不久,某游戏准备内测客户端,开发人员测试过程中发现某功能突然不灵了,之前的测试一切ok,没有发现任何异常,第一反应是,游戏内浏览器都是 ...

  4. 深入解析 composer 的自动加载原理

    PHP 自5.3的版本之后,已经重焕新生,命名空间.性状(trait).闭包.接口.PSR 规范.以及 composer 的出现已经让 PHP 变成了一门现代化的脚本语言.PHP 的生态系统也一直在演 ...

  5. laravel框架应用和composer扩展包开发

    laravel5.5+ laravel官方地址 laravel是目前最流行的php框架,发展势头迅猛,应用非常广泛,有丰富的扩展包可以应付你能想到的各种应用场景,laravel框架思想前卫,跟随时代潮 ...

  6. 使用PSR-4配合composer autoload 自动加载文件夹

    require 文件很麻烦,使用PSR-4搭配composer一次加载,终生受用. 感觉类似java中的import了,自己先记录一下最近理解的. 用composer管理自己的包吧 安装compose ...

  7. laravel composer 扩展包开发(超详细)

    laravel composer 扩展包开发(超详细) 置顶 2018年02月05日 11:09:16 Simael__Aex 阅读数:10396    版权声明:转载请注明出处:http://blo ...

  8. 详解composer的自动加载机制

    composer是一个用PHP开发的用来管理项目依赖的工具,当你在项目中声明了依赖关系后,composer可以自动帮你下载和安装这些依赖库,并实现自动加载代码. 安装composer composer ...

  9. java 启动查看jar包加载顺序并设置classpath

    本文为博主原创,转载请注明出处: 1.idea查看jar包加载顺序 jdk8 可以通过     -XX:+TraceClassPaths    参数进行查看jar包的加载顺序 jdk11 可以通过  ...

  10. thinkphp pathinfo nginx 无法加载模块:Index

    thinkphp 报了 无法加载模块:Index 错误位置 FILE: /var/multrix/wxactivity_archive/ThinkPHP/Library/Think/Dispatche ...

随机推荐

  1. C#自定义事件(简单版本)

    C#中的事件分为两种:一种是厂商微软在VS中已经内置,以供用户使用:另一种是有用户自己定义的事件: 先简单回顾下第一种: [场景1]一个Form上一个Textbox控件和Button控件,当用户按下B ...

  2. IBM Cloud Computing Practitioners 2019 (IBM云计算从业者2019)Exam答案

    Cloud Computing Practitioners 2019 IBM Cloud Computing Practitioners 2019 (IBM云计算从业者2019)Exam答案,加粗的为 ...

  3. flak_login用法

    基础的信息和全局配置这里就不多说,需要用到再斟酌也可以的.这里也是针对每个模块较为常用的进行解释说明,后期再使用过程中遇到会进行补充. Login_Manager LoginManager是一个类,有 ...

  4. 详解事务模式和Lua脚本,带你吃透Redis 事务

    摘要:Redis事务包含两种模式:事务模式和Lua脚本. 本文分享自华为云社区<一文讲透 Redis 事务>,作者: 勇哥java实战分享. 准确的讲,Redis事务包含两种模式:事务模式 ...

  5. day107:MoFang:Python操作MongoDB数据库:PyMongo

    目录 PyMongo 1.PyMongo安装 2.数据库连接 3.数据库管理 4.集合管理 5.文档管理 PyMongo 1.PyMongo安装 pip install pymongo 2.数据库连接 ...

  6. 升级:In-Place Upgrade升级MySQL5.6.26

    升级需谨慎,事前先备份 MySQL升级的实质是对数据字典的升级,数据字典有:sys.mysql.information_schema.performance_schema . MySQL升级的两种方式 ...

  7. 【SSM项目】尚筹网(二)基于Servlet3.0项目搭建:日志系统以及声明式事务

    1 日志系统 常见的日志系统实现log4j.JUL(jdk自带).log4j2.logback(和SLF4J同一个作者,能够天然衔接),这些实现就类似于java的接口实现,而SLF4J就类似于java ...

  8. 如何生成文本: 通过 Transformers 用不同的解码方法生成文本

    简介 近年来,随着以 OpenAI GPT2 模型 为代表的基于数百万网页数据训练的大型 Transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注.开放域中的条件语言生成效果令人 ...

  9. Win Pycharm + Airtest + 夜神模拟器 实现APP自动化

    前言: 前面已经讲过了Airtest的简单配置与使用了,相信大家已经对于操作Airtest没有什么问题了(#^.^#) 但是在Airtest IDE中编写代码是有局限性的,而且不能封装Airtest的 ...

  10. 突破tls/ja3新轮子

    我之前的文章介绍了SSL指纹识别 https://mp.weixin.qq.com/s/BvotXrFXwYvGWpqHKoj3uQ 很多人来问我BYPass的方法 主流的BYPASS方法有两大类: ...