首页 > 编程语言 >浅谈 thinkphp composer 扩展包加载原理

浅谈 thinkphp composer 扩展包加载原理

时间:2023-06-14 22:34:47浏览次数:65  
标签:初始化 vendor 浅谈 services composer thinkphp php 加载

浅谈 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方法


image


追进这个方法可以看到


image


追进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有这样一个配置


image


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


image


接下来直接看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>');
        }

一直到这就算结束了


写在最后

如果觉得这篇文章对你有帮助。不妨点个赞留个关注再走

标签:初始化,vendor,浅谈,services,composer,thinkphp,php,加载
From: https://www.cnblogs.com/death-satan/p/thinkphp_composer_load.html

相关文章

  • WPF之浅谈数据模板(DataTemplate)
    数据模板有什么用简而言之,数据模板能让你更方便、更灵活的显示你的各类数据。只有你想不到,没有它做不到的(感觉有点夸张,实践之后,你就觉得一点不夸张......
  • 浅谈MultipartFile中transferTo方法的坑 服务器上面使用相对路径 file.transferTo(fil
    浅谈MultipartFile中transferTo方法的坑服务器上面使用相对路径file.transferTo(filePath.getAbsoluteFile())而不是file.transferTo(filePath.getPath())绝对路径,实际生产配置服务器里面的一个文件夹。比如配置服务器文件夹前缀为/downfile/excelfile原文链接:https://ww......
  • 武汉星起航浅谈亚马逊卖家如何编辑产品关键词,提升产品排名
    作为全球最大的在线零售平台之一,亚马逊为卖家提供了丰富的机会和潜力。在亚马逊平台上,一个关键的因素是如何编辑产品关键词,以帮助产品在搜索结果中脱颖而出,并提升排名。现在,武汉星起航将分享编辑产品关键词的秘诀,助力你的产品排名飙升。首先,关键词的选择至关重要。亚马逊卖家应该仔......
  • SSM框架学习之Spring浅谈(二)
    Spring常用注解@Controller:对应SpringMVC控制层,主要用户接受用户请求并调用Service层返回数据给前端页面。@Service:对应服务层,主要涉及一些复杂的逻辑,需要用到Dao层。@Component:通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪个层,可以使用@......
  • 【浅谈JavaEE框架】Spring常用注解,自动扫描装配Bean
    1.引入context命名空间(在Spring的配置文件中)配置文件如下: Xml代码 1.xmlns:context="http://www.springframework.org/schema/context"2.http://www.springframework.org/schema/context3.http://www.springframework.org/schema/context/spring-context-2.5.xsd......
  • 浅谈API安全与人工智能生态
    随着人工智能技术的不断发展,API接口安全问题也日益凸显。API接口是现代互联网服务的核心组成部分,它提供了网络应用程序之间相互通信的方法,使得不同的软件和系统能够无缝地集成在一起,这为业务的快速部署和实现带来了巨大的便利性。然而,由于API接口开放性和易于使用的特点,同时也给......
  • 浅谈动态规划
    什么是动态规划?动态规划\((\mathbb{D}ynamic~\mathbb{P}rograming)\)算法是解决\(\color{red}多阶段决策过程最优\)的通用方法。在这类问题中,可能有多个可行解。每一个解都对应着一个值,而我们希望找到的是\(\color{red}最优值的解\)。要了解动态规划的概念,首先要知道什么是......
  • 2.5再探宝可梦、数码宝贝分类器 — 浅谈机器学习原理
    1.引入问题  在之前的课程中,我们对"参数过多就会导致过拟合"这个概念处于提出但没有证明的状态,现在来以宝可梦和数码宝贝的分类例子来说明这个问题.2.分类器定义  我们观察宝可梦和数码宝贝的图片可以发现,宝可梦的图片线条比较少,而数码宝贝的线条比较多.或许可以以边......
  • 浅谈这些年如何被MDK, IAR, GCC和厂家SDK版本兼容性“蹂躏”, 一代版本一代坑
    原创文章,转载请注明出处:https://www.armbbs.cn/forum.php?mod=viewthread&tid=119562 版本迭代是嵌入式开发永久的痛,这么多年不知道浪费了多少时间在版本迭代上。部分系统组件还好点,有个LTS长期支持版,而厂家SDK和IDE环境可谓惨不忍睹,一代版本一代坑。视频版:https://www.b......
  • [浅谈] 欧拉函数
    definition\(\varphi(n)\)表示不超过\(n\)且与\(n\)互质的正整数的个数。欧拉函数是一个数论函数(定义域为正整数)和积性函数(对于互质的正整数\(a,b\)满足\(f(a,b)=f(a)f(b)\))积性函数的性质:\(n=\prodp_i^{a_i}(p_i为质数)\)\(f(n)=\prodf(p_i^{a_i})\)。theorem......