ApiPlatform通用软删除控制器实现报错求助
问题:ApiPlatform通用软删除控制器参数解析失败
我使用ApiPlatform实现软删除逻辑:调用Delete请求时将实体的status设为0,而非直接删除数据库记录。目前能为每个实体单独编写自定义控制器,但希望实现一个通用控制器复用。我的实现思路:
- 创建
SoftDeletableInterface接口,强制实体拥有status属性及setStatus方法 - 需要软删除的实体实现该接口
- 在实体的
ApiResource配置中指定通用SoftDeleteController处理Delete操作 - 编写通用控制器代码
但运行时触发错误:无法解析__invoke方法的$entityClassName参数,提示可能未注册服务或未添加controller.service_arguments标签。当__invoke参数为具体实体类(如Channel)时可正常运行,尝试无类型声明的参数也报相同错误。
现有代码片段
SoftDeletableInterface接口
interface SoftDeletableInterface { public function setStatus(int $status): static; }
实体ApiResource配置
#[ApiResource( operations: [ new Delete( controller: ChannelSoftDeleteController::class ), ] )]
通用控制器代码
public function __invoke(string $entityClassName, $id): Response { $entityClass = 'App\Entity\' . ucfirst($entityClassName); if (!class_exists($entityClass) || !is_subclass_of($entityClass, SoftDeletableInterface::class)) { return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED); } $repository = $this->entityManager->getRepository($entityClass); $entity = $repository->find($id); if (!$entity) { return new Response(null, Response::HTTP_NOT_FOUND); } $entity->setStatus(0); $this->entityManager->persist($entity); $this->entityManager->flush(); return new Response(null, Response::HTTP_NO_CONTENT); }
解决方案
1. 利用ApiPlatform内置参数获取实体类
ApiPlatform处理请求时会自动携带当前操作对应的实体类信息,无需手动传递$entityClassName。可以通过Operation对象直接获取实体类:
use Symfony\Component\HttpFoundation\Response; use ApiPlatform\Metadata\Operation; use Doctrine\ORM\EntityManagerInterface; class SoftDeleteController { public function __construct(private EntityManagerInterface $entityManager) {} public function __invoke($data, Operation $operation): Response { // 从Operation对象中获取当前实体类 $entityClass = $operation->getClass(); // 验证实体是否实现软删除接口 if (!is_subclass_of($entityClass, SoftDeletableInterface::class)) { return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED); } // 直接使用ApiPlatform自动注入的实体对象 $data->setStatus(0); $this->entityManager->persist($data); $this->entityManager->flush(); return new Response(null, Response::HTTP_NO_CONTENT); } }
2. 统一配置实体的ApiResource
将所有需要软删除的实体的Delete操作控制器指定为通用SoftDeleteController:
#[ApiResource( operations: [ new Delete(controller: SoftDeleteController::class), // 保留其他默认操作 new Get(), new GetCollection(), new Post(), new Put() ] )] class Channel implements SoftDeletableInterface { // 实体属性定义 private int $status; // 实现接口方法 public function setStatus(int $status): static { $this->status = $status; return $this; } }
3. 确保控制器服务注册正确
Symfony默认会自动注册src/Controller目录下的控制器并添加controller.service_arguments标签。如果控制器在自定义目录,需在config/services.yaml中手动配置:
services: App\Controller\SoftDeleteController: autowire: true tags: ['controller.service_arguments']
4. 可选:添加Doctrine过滤器自动过滤软删除实体
为避免查询时返回已软删除的实体,可添加Doctrine全局过滤器:
// src/Filter/SoftDeleteFilter.php use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Filter\SQLFilter; class SoftDeleteFilter extends SQLFilter { public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string { if (!$targetEntity->reflClass->implementsInterface(SoftDeletableInterface::class)) { return ''; } return "$targetTableAlias.status != 0"; } }
在config/packages/doctrine.yaml中启用过滤器:
doctrine: orm: filters: soft_delete: class: App\Filter\SoftDeleteFilter enabled: true
内容的提问来源于stack exchange,提问作者Stami
相关产品推荐
相关产品推荐

