Symfony:我如何才能同时获得标记的服务和已处理的配置? [英] Symfony: How can I get hold of tagged services and processed configuration at the same time?

查看:24
本文介绍了Symfony:我如何才能同时获得标记的服务和已处理的配置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 symfony 配置来确定如何连接一些标记服务,但遇到了问题.我试图将问题归结为尽可能少的代码来帮助解释,但仍然 - 抱歉篇幅太长!

I'm trying to symfony Configuration to determine how to wire some tagged services, but am running into problems. I've tried to boil the problem down into as little code as possible to help explain, but still - sorry for the length!

这是事情的配置部分...

Here's the configuration part of things...

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder('acme_test');
        $treeBuilder
            ->getRootNode()
            ->addDefaultsIfNotSet()
            ->children()
                ->scalarNode('email_sender')->isRequired()->end()
                ->scalarNode('email_title')->defaultValue('Notification email')->end()
            ->end();

        return $treeBuilder;
    }
}

acme_test:
    email_sender: 'test@example.com'

我还有一个任意的服务,它接受 $emailSender 和 $emailTitle.它已在 services.yaml 中使用任意服务"标签进行标记:

I've also got an arbitrary service which takes $emailSender and $emailTitle. It's been tagged with the 'arbitrary-services' tags in services.yaml:

class ArbitraryService
{
    protected $emailSender;

    protected $emailTitle;

    public function __construct(string $emailSender, string $emailTitle)
    {
        $this->emailSender = $emailSender;
        $this->emailTitle = $emailTitle;
    }
}

services:
    App\Acme\TestBundle\ArbitraryService:
        tags: ['arbitrary-services']

Symfony 文档告诉我做我的 标记在 CompilerPass 中查找服务 - 足够公平:

The Symfony documentation tells me to do my tagged services finding in a CompilerPass - fair enough:

class AcmeTestCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $configs = $container->getExtensionConfig('acme_test');

        $taggedServices = $container->findTaggedServiceIds('arbitrary-services');

        // Great - got the tagged service definitions
        // Now going to wire things passed via config into those services (e.g. via binding)

        dump('From CompilerPass:');
        dump($taggedServices);
        dump($configs);
    }
}

在我的完整用例中,我想标记不同的服务目录,以使它们根据配置选项接收不同的参数(例如,标记为 inject.alpha 的服务根据 acme -> alpha 中的配置键获取参数).

In my full use-case, I want to tag different directories of services to cause them to receive different params based upon config options (e.g. services tagged with inject.alpha get parameters based upon config keys in acme -> alpha).

问题是,此时,虽然标记服务返回正常,但配置尚未处理,因此我们缺少具有 defaultValue 的 email_title 键:

The problem tho' is that at this point, whilst the tagged services return fine, the configuration has not been processed, and so we're missing the email_title key which has a defaultValue:

wobble@pop-os:~/test$ bin/console c:c
"From CompilerPass:"
array:1 [
  "App\Acme\TestBundle\ArbitraryService" => array:1 [
    0 => []
  ]
]
array:1 [
  0 => array:1 [
    "email_sender" => "test@example.com"
  ]
]

另一方面,如果我在 Extension/load() 类中进行检查...

If I check within the Extension / load() class on the other hand...

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

        $taggedServices = $container->findTaggedServiceIds('arbitrary-services');

        dump('From load()');
        dump($taggedServices);
        dump($config);
    }
}

我会发现我有完全处理的配置(是的!)但没有标记的服务,因为我可能为时过早(因此文档告诉我使用 CompilerPass):

I'll find that I have the fully-processed configuration (yey!) but no tagged services as presumably I'm too early for that (hence the docs telling me to use a CompilerPass):

wobble@pop-os:~/test$ bin/console c:c
"From load()"
[]
array:2 [
  "email_sender" => "test@example.com"
  "email_title" => "Notification email"
]

谁能告诉我是否可以同时获取已处理的配置和标记的服务?谢谢!

Can anyone please tell me if it's possible to get hold of both the processed configuration and the tagged services at the same time? Thanks!

我已将重现我的问题的测试代码推送到 github 存储库上:https://github.com/WubbleWobble/symfony-stack-overflow-1

I've pushed the test code that reproduces my problem up on a github repo here: https://github.com/WubbleWobble/symfony-stack-overflow-1

推荐答案

设法找到解决方案.将编译器传递移动到扩展类中,然后通过类属性将处理过的配置共享给它:)

Managed to figure a solution. Moved the compiler pass inside the extension class and then shared the processed config across to it via a class property :)

class AcmeTestExtension extends Extension implements CompilerPassInterface
{
    /** @var array */
    protected $processedConfig;

    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $this->processedConfig = $this->processConfiguration($configuration, $configs);
    }

    public function process(ContainerBuilder $container)
    {
        $taggedServices = $container->findTaggedServiceIds('arbitrary-services');

        // Great - got the tagged service definitions
        // Now going to wire things passed via config into those services (e.g. via binding)

        dump('From CompilerPass:');
        dump($taggedServices);
        dump($this->processedConfig);
    }
}

"From CompilerPass:"
array:2 [
    "App\Acme\TestBundle\ArbitraryService" => array:1 [
        0 => []
    ]
]
array:2 [
    "email_sender" => "test@example.com"
    "email_title" => "Notification email"
]

这篇关于Symfony:我如何才能同时获得标记的服务和已处理的配置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆