Api Platform 3.0:定义带Provider/Processor的Post子资源路由及获取Client实例
Api Platform 2.7子资源Post请求获取关联Client实例解决方案
问题场景
我们后端采用资源与实体分离架构,已从Api Platform 2.6通过php bin/console api:upgrade-resource命令升级至2.7(目标版本3.0)。当前在创建子资源时,遇到带Provider、Processor和自定义控制器的Post请求无法正确获取关联Client实例的问题。
现有Basket资源路由配置:
#[ApiResource( uriTemplate: '/clients/{id}/baskets.{_format}', processor: BasketDataPersister::class, provider : ClientDataProvider::class, status: 200, denormalizationContext: ['groups' => ['write', 'write:Basket']], normalizationContext: ['groups' => ['read', 'read:Basket']], operations: [ new Post(controller: PostClientBasketController::class, normalizationContext: ['groups' => ['read', 'read:Basket']], denormalizationContext: ['groups' => ['write', 'write:Basket']], security: 'is_granted(\'ROLE_USER\')', requirements: ['id' => '^[a-fA-F0-9]{12}$']), ], )]
控制器需要接收Client实例:
public function __invoke(Client $data, Request $request, ?string $_format): Basket|JsonResponse { /** @var Basket $basket */ $basket = $this->serializer->deserialize($request->getContent(), Basket::class, $_format); $basket ->setClient($data->getId()) ->setOrganizationId($data->getOrganizationId()) ; return $basket; }
此前尝试配置uriVariables关联Client资源但未生效:
uriVariables: ['id' => new Link( fromClass: \App\Resource\Client::class, identifiers: ['id'] )],
解决步骤
1. 正确配置uriVariables关联Client资源
将uriVariables配置放到ApiResource注解的顶层,确保路由参数与Client资源正确绑定:
#[ApiResource( uriTemplate: '/clients/{id}/baskets.{_format}', processor: BasketDataPersister::class, provider : ClientDataProvider::class, status: 200, denormalizationContext: ['groups' => ['write', 'write:Basket']], normalizationContext: ['groups' => ['read', 'read:Basket']], // 新增正确的uriVariables配置 uriVariables: [ 'id' => new Link( fromClass: \App\Resource\Client::class, identifiers: ['id'] ) ], operations: [ new Post(controller: PostClientBasketController::class, normalizationContext: ['groups' => ['read', 'read:Basket']], denormalizationContext: ['groups' => ['write', 'write:Basket']], security: 'is_granted(\'ROLE_USER\')', requirements: ['id' => '^[a-fA-F0-9]{12}$']), ], )]
2. 确保Client资源已被Api Platform管理
Client类必须添加#[ApiResource]注解,否则Api Platform无法识别该资源类型,无法完成实例注入:
#[ApiResource( // 根据需求配置Client资源的操作、序列化组等 )] class Client { // 类定义 }
3. 验证ClientDataProvider实现
确保ClientDataProvider正确实现ProviderInterface,能够根据传入的标识符获取对应的Client实例:
class ClientDataProvider implements ProviderInterface { public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null { // 实现根据$uriVariables['id']获取Client实例的逻辑 } }
4. 控制器参数接收
控制器的__invoke方法中直接声明Client类型参数即可,Api Platform会自动根据路由参数注入匹配的实例,无需额外处理。
内容的提问来源于stack exchange,提问作者Xbattlax
相关产品推荐
相关产品推荐

