【问题标题】:Symfony 5.4 environmental variables in services.yaml::parametersservices.yaml::parameters 中的 Symfony 5.4 环境变量
【发布时间】:2022-01-25 15:20:38
【问题描述】:

最近我决定在其中一个项目中使用 Symfony 5.4 容器来提供一些全面的 DI。它像往常一样运行良好,直到我尝试在 services.yaml::parameters 部分使用一些环境变量。

文档声明我应该绑定到一个环境变量

# services.yaml
parameters:
  my_var: '%env(SOME_ENV_VAR)%'

它将在第一次调用时从环境变量中解决。好的。我这样做了,我得到了什么:

echo $container->getParameter('my_var');
// env_b057c2b619f37f36_SOME_ENV_VAR_222ed306d0932595cbdeada438ccbb2a

我确实在$_SERVER$_ENV 中看到了SOME_ENV_VAR。我还尝试了Dotenv 组件,以确保我没有遗漏任何东西,但徒劳无功。任何环境变量都会变成这种env_{hash}_{VAR_NAME}_{hash} 模式。

我没有使用完整的 Symfony 安装,只是一些备用组件。我错过了什么?我应该在容器构建阶段手动填充每个环境变量吗?


容器实例化如下:

// $_ENV and $_SERVER already contain `SOME_ENV_VAR` here

require_once __DIR__ . '/vendor/autoload.php';

// `use` statements go here

$containerBuilder = new ContainerBuilder();

$loader = new YamlFileLoader(
  $containerBuilder,
  new FileLocator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'config']))
);

$loader->load('services.yaml');

$containerBuilder->compile();

$container = $containerBuilder;

$my_var = $container->getParameter('SOME_ENV_VAR');

echo $my_var;

【问题讨论】:

  • PHP 运行时不会自动读取环境变量。您可以通过简单的 var_dump($_ENV); 来确认这一点。设置值由您决定。在编译容器之前添加putenv('SOME_ENV_VAR','value');,错误应该会消失。您还应该能够使用 Dotenv 组件从 .env 文件中读取变量。可能想重新审视您尝试过的内容。
  • @yivi 我同意,我尝试将该参数作为 arg 传递给服务,并且值是相同的。我在->compile() 之后使用容器。
  • 好的,我仍然需要查看更多内容才能知道发生了什么。上述代码和配置不足以可靠地重现问题并为您提供解决方案。
  • @Cerad Env 变量完好无损。它们确实存在于系统环境中,正如我之前在我的问题中所说的,我确实在容器编译前后看到了 $_ENV$_SERVER 两者,这就是我想知道的原因。

标签: php symfony dependency-injection symfony5


【解决方案1】:

根据你更新的sn-p,你需要使用:

$container->compile(true); // false is the default

该参数称为resolveEnvPlaceholders。我记得前段时间它抓住了我。

仍然觉得你设置了 $_ENV 有点令人费解,但我会相信你的话。

这是我挖出的一个旧测试用例,仍然有效:

use Symfony\Component\DependencyInjection\ContainerBuilder;

class Service 
{
  public function __construct(string $dsn)
  {
    echo $dsn . "\n";
  }
}
$container = new ContainerBuilder();
$container->autowire(Service::class,Service::class)->setPublic(true)
    ->setArguments([
        '%env(DSN)%'
  ]);
$container->setParameter('my_var','%env(DSN)%');

putenv('DSN=dsn_value');
$container->compile(true);

$service = $container->get(Service::class);

echo $container->getParameter('my_var') . "\n";

【讨论】:

  • 天啊。多么尴尬。非常感谢!这有点奇怪,我在写关于 env vars 分辨率的文章时找不到关于 $resolveEnvPlaceholders 的某处提到它,但也许我完全错过了它。
  • 不确定它是否记录在案,除了参数名称。 Symfony 组件文档通常有点缺乏。在框架内,编译后的容器被写入一个文件,然后为每个请求重新加载。在这种情况下,您希望使用当前的 env 值而不是编译时的值。所以我猜这就是它默认为 false 的原因。
  • 是的,缓存容器的环境变量也会被缓存(true 时),要更改环境变量,您应该重新编译容器。在这种情况下要记住一些事情。
【解决方案2】:

ContainerBuilder::compile() 的签名是:

public function compile(bool $resolveEnvPlaceholders = false)

如果你不传递它true,它不会解析环境变量的占位符。

此外,您的示例存在问题。

你在打电话:

$my_var = $container->getParameter('SOME_ENV_VAR');

但是SOME_ENV_VAR不是容器参数,而是环境变量。正确的调用是:

$my_var = $container->getParameter('my_var');

整个事情是:

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

require_once __DIR__ . '/vendor/autoload.php';

$containerBuilder = new ContainerBuilder();

$loader = new YamlFileLoader(
    $containerBuilder,
    new FileLocator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'config']))
);

$loader->load(__DIR__ . '/services.yaml');

$containerBuilder->compile(true);

$container = $containerBuilder;
$my_var    = $container->getParameter('my_var');

echo $my_var;

【讨论】:

  • 谢谢。直到现在我才真正阅读过compile() 的签名,而且文档中似乎没有提到解析环境变量应该是true。感谢您闪电般的快速反应和参与!欣赏!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2016-10-02
  • 2012-05-25
  • 2014-09-30
相关资源
最近更新 更多