如何让API Platform 3在一对多关联中应用软删除扩展?
解决API Platform 3关联查询未应用Gedmo软删除过滤的问题
方法一:在Doctrine关联映射中直接添加过滤条件
最直接的方式是在实体的关联注解里加上@ORM\Where,让Doctrine在加载关联数据时自动过滤已软删除的记录。
比如在User实体的offers关联上:
// src/Entity/User.php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class User { // ... 其他字段 /** * @ORM\OneToMany(targetEntity=Offer::class, mappedBy="user") * @ORM\Where(clause="deleted_at IS NULL") */ private $offers; // ... getter/setter }
这个方式属于Doctrine层面的全局过滤,不管是API Platform查询还是其他地方调用关联,都会自动排除已软删除的Offer实体。
方法二:自定义API Platform查询扩展,覆盖子资源查询
如果不想修改实体映射,或者需要更灵活的控制,可以自定义一个支持上下文的查询扩展,确保关联查询(子资源)也应用软删除过滤:
- 创建扩展类:
// src/Doctrine/Orm/Extension/SoftDeleteableExtension.php use ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; use Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter; class SoftDeleteableExtension implements ContextAwareQueryExtensionInterface { public function __construct(private readonly SoftDeleteableFilter $softDeleteableFilter) { } public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { $this->applySoftDeleteFilter($queryBuilder, $resourceClass); } public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void { $this->applySoftDeleteFilter($queryBuilder, $resourceClass); } private function applySoftDeleteFilter(QueryBuilder $queryBuilder, string $resourceClass): void { $rootAlias = $queryBuilder->getRootAliases()[0]; $this->softDeleteableFilter->addFilterConstraint($rootAlias, $resourceClass, $queryBuilder); } }
- 注册服务(如果使用Symfony的autoconfigure可自动注册,否则在
services.yaml配置):
# config/services.yaml services: App\Doctrine\Orm\Extension\SoftDeleteableExtension: arguments: ['@gedmo.filter.softdeleteable'] tags: - { name: api_platform.doctrine.orm.query_extension, priority: 10 }
设置优先级为10,确保它在其他默认扩展之前执行,保证过滤条件被正确添加。
方法三:启用Gedmo的Doctrine过滤器
确保Gedmo的SoftDeleteable过滤器已经在Doctrine配置中启用,这样Doctrine会自动为所有查询(包括关联查询)添加软删除过滤:
# config/packages/doctrine.yaml doctrine: orm: filters: softdeleteable: class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter enabled: true
这个方式是全局启用,所有Doctrine查询都会自动排除已软删除的实体,包括API Platform的关联查询。若有特殊场景需要查询已删除实体,可临时禁用过滤器。
内容的提问来源于stack exchange,提问作者Stephan Vierkant
相关产品推荐
相关产品推荐

