ApiPlatform 3.1升级至3.2后GroupsDenormalizer注入异常排查
问题原因
ApiPlatform 3.2.0新增了ValidationExceptionNormalizer,这个归一化器会自动装饰api_platform.serializer.normalizer.item服务。你的GroupsDenormalizer同样装饰该服务,但仅实现了DenormalizerInterface,未实现NormalizerInterface。当依赖注入容器构建装饰链时,若ValidationExceptionNormalizer尝试注入你的GroupsDenormalizer作为其装饰对象,就会因类型不匹配抛出TypeError——因为ValidationExceptionNormalizer的构造函数要求参数是NormalizerInterface类型,而你的类只实现了反归一化接口。
解决思路
1. 让GroupsDenormalizer同时实现两个接口
修改你的GroupsDenormalizer类,使其同时实现NormalizerInterface和DenormalizerInterface,并将归一化相关逻辑委托给被装饰的服务:
<?php namespace App\Security; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\DependencyInjection\Attribute\AsDecorator; #[AsDecorator(decorates: 'api_platform.serializer.normalizer.item')] class GroupsDenormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { public function __construct(private readonly NormalizerInterface&DenormalizerInterface $decorated) {} // 委托归一化逻辑给被装饰服务 public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { return $this->decorated->normalize($object, $format, $context); } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $this->decorated->supportsNormalization($data, $format, $context); } // 保留你原有的反归一化逻辑 public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { // 你的自定义反归一化代码 return $this->decorated->denormalize($data, $type, $format, $context); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { // 你的自定义支持判断逻辑 return $this->decorated->supportsDenormalization($data, $type, $format, $context); } public function setSerializer(SerializerInterface $serializer): void { if ($this->decorated instanceof SerializerAwareInterface) { $this->decorated->setSerializer($serializer); } } // 若需要,实现getSupportedTypes方法(Symfony 6.3+) public function getSupportedTypes(?string $format): array { return $this->decorated->getSupportedTypes($format); } }
2. 调整装饰器优先级(可选)
如果接口修改后仍有问题,可以通过调整priority参数控制装饰链顺序,确保ValidationExceptionNormalizer先于你的GroupsDenormalizer被应用:
#[AsDecorator(decorates: 'api_platform.serializer.normalizer.item', priority: -100)]
(优先级数值越低,装饰器越晚被应用,即越靠近原始服务)
3. 验证服务定义
确保services.yaml中没有冲突的手动配置,若之前手动定义过装饰,删除相关配置,完全依赖#[AsDecorator]属性即可。
内容的提问来源于stack exchange,提问作者Alexandre Tranchant
相关产品推荐
相关产品推荐

