当前位置: 首页 > 知识库问答 >
问题:

Symfony:如何同时获得标记服务和已处理配置?

沈德寿
2023-03-14

我试图symfony配置,以确定如何连接一些标记的服务,但我遇到了问题。我试图把这个问题浓缩成尽可能少的代码来帮助解释,但是仍然——抱歉太长了!

这里是配置部分的东西。。。

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中,它被标记为任意服务标签:

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中查找标记的服务-足够公平:

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中的配置键获取参数)-

问题是,此时,虽然标记的服务返回正常,但配置尚未处理,因此我们缺少具有默认值的电子邮件标题键:

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"
  ]
]

另一方面,如果我检查扩展/加载()类...

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):

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

有人能告诉我是否有可能同时获得处理后的配置和标记的服务吗?谢谢!

我在github repo上推送了重现我问题的测试代码:https://github.com/WubbleWobble/symfony-stack-overflow-1

共有1个答案

南门嘉
2023-03-14

设法想出一个解决办法。将编译器传递移到扩展类中,然后通过类属性将已处理的配置共享给扩展类:)

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"
]
 类似资料:
  • 服务如何明确它在请求/响应中接受/服务作为MTOM附件的二进制数据? 客户端如何正确识别二进制数据可以通过使用给定服务的MTOM附件发送/获取?

  • 当我调用服务在日志文件中获取此信息消息时,它工作正常,但将此消息写入日志文件: php.INFO:User Deprecated:The“logger”服务是私有的,从容器中获取它是不推荐的,因为Symfony 3.2,并且将在4.0中失败。您应该公开服务,或者停止直接使用容器,改用依赖项注入。{“异常”:“[object](ErrorException(代码:0):用户已弃用:记录器\”\“服务

  • 我有一个基于strut的应用程序,我在其中调用我的Restful Web Service。我的实际服务调用如下所示: 呼叫通过只是罚款,但我想处理的情况下,如果我的服务是关闭,我想超时1分钟,而不是等待这么长时间。

  • 我正在尝试迁移到symfony 3.3并使用新功能/服务: 所以services.yml我有: 我声明我的小枝扩展为: 和此服务的构造函数: 似乎一切都好,但我得到了这个错误: 也不知道如何修复它。

  • 问题内容: 标记界面没有任何东西。它仅包含接口声明,然后JVM如何对实现此标记接口的类进行处理? 我们可以创建任何新的标记器接口吗? 问题答案: 您的问题确实应该是 编译器 如何处理标记接口,而答案是: 与其他接口没有什么不同 。例如,假设我声明了一个新的标记接口: …然后声明一个实现的类: 我现在可以通过type的引用来引用的实例: …,并(在运行时)检查对象是否实现: 后一种情况通常是使用标记

  • 下面是我的代码片段: 现在java用'unhandled exception type SQLException)标记指示语句(以及后面的所有语句)。gfsql.dosql抛出此异常并定义为: public ResultSet doSQL(String sqlCommand)抛出SQLException{ 有趣的是--如果我像这样重复“catch”块: 未标记“未处理”错误。(但是,重复的catc