Symfony 4 - 供应商包找不到标记的自动装配服务

Symfony 4 - vendor bundle cannot find tagged autowired service

我制作了简单的 API 包,它(将)在项目之间共享。每个 object/entity 都有自己的配置,说明哪些字段以及它们将如何序列化(分解为标量值)。它们将如何序列化取决于选择的标准化器。现在只有一个默认规范化程序将值识别为标量、可迭代对象或对象。到目前为止效果很好。当您需要像 DateTime 这样的特定序列化时(您不想将对象分解为隐式标量值,而是设置输出格式),您只需创建一个新的规范化程序来相应地处理该对象。

由于要使用的规范化器在配置yaml文件中定义并且可以从其他来源传递,因此规范化器的名称必须是字符串。

        App\Entity\Example\Category:
            normalizer: asyf.api.service.normalizer.default
            fields:
                title:
                    expose: true
                slug:
                    expose: false
                items:
                    orderBy:
                        title:
                            priority: 1
                            direction: DESC
                    limit: 2
                    expose: true

标准化器被标记为 "asyf.api.normalizer"。因为这是作为供应商包创建的,所以我使用它的依赖注入扩展来按标签加载服务,并将它们注入到存储它们的 NormalizersManager 服务中,并可以通过键名

恢复它们
class AsyfApiExtension extends Extension
{
    /**
     * @param array $configs
     * @param ContainerBuilder $container
     *
     * @throws \Exception
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
        $loader->load('services.yml');

        $container->setParameter('asyf_api', $config);

        $normalizerManagerDefinition = $container->findDefinition('asyf.api.service.normalizers_manager');
        $defaultNormalizerId = 'asyf.api.service.normalizer.default';
        $defaultNormalizerReference = new Reference($defaultNormalizerId);
        $normalizerManagerDefinition->addMethodCall('add', array($defaultNormalizerId, $defaultNormalizerReference));

        $taggedNormalizers = $container->findTaggedServiceIds('asyf.api.normalizer');

        foreach ($taggedNormalizers as $id => $tags) {
            $normalizerReference = new Reference($id);
            $normalizerManagerDefinition->addMethodCall('add', array($id, $normalizerReference));
        }
    }
}

现在问题来了: AsyfApiExtension::load 中的这个容器看不到其范围之外的标记服务。它只是看到这个包中定义的服务。因此,当我创建新的自动装配规范器并使用标签在 config/services.yaml 中注册它时,供应商包看不到它并且它没有添加到 NormalizersManager 服务中,因此无法使用。

    App\Service\Search\Normalizer\SearchResultNormalizer:
        public: true
        tags:
            - { name: 'asyf.api.normalizer' }

为了解决这个问题,我可以手动添加它,但后来我放弃了这种自动配置的想法。有没有办法让新的自动装配规范器在供应商扩展负载中可访问?感谢任何想法

我找到了解决方案,我必须重写一些代码,但这里是:

    asyf.api.service.normalizers_manager:
        class: App\Service\Search\NormalizersManager
        arguments: [!tagged asyf.api.normalizer]

!tagged asyf.api.normalizer 注入带有标签 asyf.api.normalizer

的服务集合