浅谈 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. 003-Cruehead-CrackMeV3

    第二个需要写注册机 首先查看文件,打开文件,什么也没有,help ->about,弹出下面的弹窗 看来是没有什么线索,直接放进OD里面 这里有一个函数CreatFileA,这个函数目的是访问一个 ...

  2. 机器学习08DAY

    线性回归 波士顿房价预测案例 步骤 导入数据 数据分割 数据标准化 正规方程预测 梯度下降预测 # 导入模块 import pandas as pd # 导入数据 from sklearn.model ...

  3. golang pprof 监控系列(3) —— memory,block,mutex 统计原理

    golang pprof 监控系列(3) -- memory,block,mutex 统计原理 大家好,我是蓝胖子. 在上一篇文章 golang pprof监控系列(2) -- memory,bloc ...

  4. 迁移学习(TSRP)《Improving Pseudo Labels With Intra-Class Similarity for Unsupervised Domain Adaptation》

    论文信息 论文标题:Improving Pseudo Labels With Intra-Class Similarity for Unsupervised Domain Adaptation论文作者 ...

  5. CentOS安装时钟同步服务

    使用chrony用于时间同步 yum install chrony -y vim /etc/chrony.conf cat /etc/chrony.conf | grep -v "^#&qu ...

  6. day3 函数的定义和调用,练习编写简单的程序(记录3)

    0331.h #ifndef _0331_H #define _0331_H /************************************************************ ...

  7. Laplace分布算子开发经验分享

    摘要:Laplace 用于 Laplace 分布的概率统计与随机采样. 本文分享自华为云社区<Laplace分布算子开发经验分享>,作者:李长安. 1.任务解析 详细描述: Laplace ...

  8. python:字典中遍历key对应的value值

    问题描述:python在一个字典中想要遍历某个可以对应的value值. 效果如下: 方法一:使用循环遍历所有的key,然后对比输入的值跟便利出来的key有没有相同的 constellation = [ ...

  9. Get Your Wish

    Get Your Wish (https://www.luogu.com.cn/problem/P7262) 一个模拟题 解读一下题目:简单来说就是在现在重力的方向上,如果有水滴和电子元件就GG,否则 ...

  10. Java学习笔记04

    1. 循环进阶 1.1 无限循环 概念 ​ 循环一直停不下来,又叫死循环. for格式 for (;;) { 循环语句; } while格式 while (true) { 循环语句; } do...w ...