ApiPlatform 2.7升级3.0:POST路由Abstract Item Normalizer报错
API Platform 2.7升级3.0后POST数组请求报错的解决方法
问题核心
升级后POST包含多个对象的数组请求时,触发类型错误:ApiPlatform\Serializer\AbstractItemNormalizer::canAccessAttributePostDenormalize(): Argument #3 ($attribute) must be of type string, int given,本质是3.0版本的ItemNormalizer不再支持直接处理数组请求,序列化器误将数组索引(int类型)当作资源属性名传入校验方法,导致类型不匹配。
解决方案
1. 配置实体支持批量创建
在实体的#[ApiResource]注解中,明确为POST集合操作指定批量处理的输入类型,让API Platform使用CollectionNormalizer而非ItemNormalizer处理请求:
use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\Collection; #[ApiResource( collectionOperations: [ 'post' => [ 'input' => Collection::class, 'denormalization_context' => [ // 指定集合内的实体类型 'collection_type' => YourEntity::class, // 可选:添加需要的序列化组 'groups' => ['your_entity:write'] ], ], ], )] class YourEntity { // 实体属性定义 private string $name; private string $width; private int $priority; // getter/setter... }
2. 使用DTO接收批量请求(推荐)
如果需要更灵活的批量处理逻辑,可创建DTO类封装实体数组,再通过自定义处理器完成DTO到实体的转换:
// src/DTO/BatchYourEntityInput.php class BatchYourEntityInput { /** * @var YourEntity[] */ public array $items; }
更新实体的API配置:
#[ApiResource( collectionOperations: [ 'post' => [ 'input' => BatchYourEntityInput::class, 'processor' => BatchYourEntityProcessor::class, ], ], )] class YourEntity { // ... }
自定义处理器示例:
// src/Processor/BatchYourEntityProcessor.php use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use Doctrine\ORM\EntityManagerInterface; class BatchYourEntityProcessor implements ProcessorInterface { public function __construct(private EntityManagerInterface $em) {} public function process($data, Operation $operation, array $uriVariables = [], array $context = []) { foreach ($data->items as $item) { $this->em->persist($item); } $this->em->flush(); return $data->items; } }
3. 排查自定义序列化逻辑
如果项目中有自定义Normalizer或EventSubscriber,检查是否存在3.0版本兼容问题:
- 确保自定义Normalizer不会拦截数组请求,错误使用ItemNormalizer处理
- 移除2.7版本中针对批量请求的临时兼容代码,改用3.0标准处理方式
关键说明
之前通过uriVariables解决的是URL路径变量问题,与本次请求体的序列化逻辑无关,因此不适用。3.0版本对序列化器职责划分更严格,ItemNormalizer仅处理单个资源,批量请求必须由CollectionNormalizer或自定义DTO处理器处理。
内容的提问来源于stack exchange,提问作者fuqeba
相关产品推荐
相关产品推荐

