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
的服务集合
我制作了简单的 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