You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP-DI配置文件中使用构建时传入的变量?

PHP-DI:如何在配置文件中使用构建时变量完成复杂计算

问题描述

在构建PHP-DI容器时,需要基于外部传入的构建时变量(比如示例里的$number)在config.php里执行复杂计算(实际需求是根据指定目录查找要注入的服务),但config.php里无法直接访问PHP-DI容器,导致没法读取已添加的number定义,现有代码无法运行。

容器构建代码(可正常运行):

<?php

use DI\Container;
use DI\ContainerBuilder;

class MyContainerBuilder
{
    // @param number 是后续要使用的构建时(配置)变量
    public function build(int $number): Container
    {
        $builder = new \DI\ContainerBuilder();
        $builder->addDefinitions(['number' => $number]);
        // 希望在config.php中进行复杂计算
        $builder->addDefinitions(__DIR__ . '/config.php');
        // 生产环境中可编译容器,使config.php的复杂计算仅执行一次
        return $builder->build();
    }
}

问题代码(config.php):

<?php

$number = $container->get('number');
// 复杂计算:
$number += 1;

return [
    'improvedNumber' => $number,
];

解决方案

方案1:利用PHP变量作用域传递参数

PHP中,include的文件会继承当前作用域的变量,所以直接在build方法里保留$number变量,修改config.php直接使用该变量即可:

修改后的config.php:

<?php

// 直接用当前作用域的$number
$number += 1;

return [
    'improvedNumber' => $number,
];

同时调整MyContainerBuilder的构建逻辑,手动include并传入结果:

public function build(int $number): Container
{
    $builder = new \DI\ContainerBuilder();
    $builder->addDefinitions(['number' => $number]);
    
    // 手动加载config.php,利用变量作用域传递$number
    $configDefs = include __DIR__ . '/config.php';
    $builder->addDefinitions($configDefs);
    
    return $builder->build();
}

这个方案完全符合你的需求,config.php里的计算逻辑保留不变,生产环境编译容器时,计算只会执行一次。

方案2:把config.php改成带参数的函数

如果不想依赖隐式的变量作用域,可将config.php改为返回一个接收参数的函数,显式传递构建时变量:

修改后的config.php:

<?php

return function(int $number) {
    $number += 1;
    
    return [
        'improvedNumber' => $number,
    ];
};

然后在构建类中调用该函数:

public function build(int $number): Container
{
    $builder = new \DI\ContainerBuilder();
    $builder->addDefinitions(['number' => $number]);
    
    // 加载函数并传入$number获取定义
    $configFn = include __DIR__ . '/config.php';
    $builder->addDefinitions($configFn($number));
    
    return $builder->build();
}

这种写法更显式,避免了作用域依赖,代码可读性更强。

方案3:直接在构建类中处理服务查找(针对实际需求)

针对你实际要查找目录中服务的需求,也可以把服务扫描逻辑直接放在MyContainerBuilder里,无需依赖config.php:

public function build(string $serviceDir): Container
{
    $builder = new \DI\ContainerBuilder();
    
    // 扫描目录生成服务定义
    $serviceDefs = [];
    $files = scandir($serviceDir);
    foreach ($files as $file) {
        if (pathinfo($file, PATHINFO_EXTENSION) !== 'php') continue;
        $className = pathinfo($file, PATHINFO_FILENAME);
        // 自动注入服务类
        $serviceDefs[$className] = \DI\autowire($className);
    }
    
    $builder->addDefinitions($serviceDefs);
    
    return $builder->build();
}

这种方式把逻辑集中在容器构建类里,减少了额外配置文件的依赖。

内容的提问来源于stack exchange,提问作者Lord Bo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:34:54