【问题标题】:Inject configuration in Symfony在 Symfony 中注入配置
【发布时间】:2018-01-06 02:05:56
【问题描述】:

我使用的是 Symfony 4,有一个配置文件需要以数组的形式注入到命令App\Command\FooCommand 中。我在App\Kernel::configureContainer()注册了一个自定义DI扩展,用于验证自定义配置文件(为了开发方便,配置很大,在开发过程中会经常更改)。该命令的构造函数是public function __construct(Foo $foo, array $config),我希望配置作为第二个参数。

现在我该如何把这个配置放在那里?文档中提到了参数,但它不是参数。我正在考虑更改命令的定义并在 Extension::load 方法中添加此参数,如下所示:

class FooExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = $this->getConfiguration($configs, $container);
        $config = $this->processConfiguration($configuration, $configs);

        //inject the configuration into the command
        $fooCmdDef = $container->getDefinition(FooCommand::class);
        $fooCmdDef->addArgument($config);
    }
}

但它以错误结束

您请求了一个不存在的服务“App\Command\FooCommand”。

但是该命令必须已自动注册为服务。

我做错了什么以及如何注入此配置?

【问题讨论】:

    标签: php symfony symfony4


    【解决方案1】:

    您无法访问 DI 扩展类中的任何服务因为容器尚未编译。对于您的情况,通常创建一个Compiler Pass,您将能够在其中检索所需的服务并对其应用任何修改。

    例如,您可以在存储配置的容器扩展中创建一个参数:

    class FooExtension extends Extension
    {
        public function load(array $configs, ContainerBuilder $container)
        {
            $configuration = $this->getConfiguration($configs, $container);
            $config = $this->processConfiguration($configuration, $configs);
    
            //create a container parameter
            $container->setParameter('your_customized_parameter_name', $config);
        }
    }
    

    然后在编译器传递中检索您需要的内容,然后应用一些修改:

    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Definition;
    use Symfony\Component\DependencyInjection\Reference;
    
    class YourCompilerPass implements CompilerPassInterface
    {
        /**
         * {@inheritdoc}
         */
        public function process(ContainerBuilder $container)
        {
            # retrieve the parameter
            $config = $container->getParameter('your_customized_parameter_name');
            # retrieve the service
            $fooCmdDef = $container->getDefinition(FooCommand::class);
            # inject the configuration
            $fooCmdDef->addArgument($config);
    
            # or you can also replace an argument
            $fooCmdDef->replaceArgument('$argument', $config);
        }
    }
    

    【讨论】:

    • 那么唯一的方法就是使用这些服务定义操作?我正在考虑在 YML 文件中配置它,这样会更整洁。不过好像不太可能。
    • @Sergey 我不确定你所说的“我想在 YML 文件中配置它会更整洁。”是什么意思。在扩展类中(在 Symfony 包之外使用)你只能加载配置文件,使用 ConfigurationClass 来验证它的数据,但是如果你需要访问任何服务并使用它对其进行一些修改,则需要编译器通过那个数据。如果你能更好地描述你的具体用例,我可能会更具体。
    • 我可以将配置的parameters 部分中描述的参数注入到通过名称引用它们的服务中,例如%foo.bar%。就我而言,我需要注入整个配置部分,而不是参数。我的意思是我是否可以对它做同样的事情,比如在 yaml 文件中使用服务参数数组中的根配置键
    • @Sergey 好吧。 parameters 部分中的参数主要用作key: value 对,但也可以是key: [arrays]。我从来没有这样使用过它,但我认为您可以使用 foo: [arrays] 之类的键将整个部分放入 parameters 部分中,并在 service 参数中引用它,因为您已经知道 %foo% 。从未测试过,但应该可以工作,并且不需要使用 FooExtension 类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 2015-12-05
    相关资源
    最近更新 更多