Symfony4中如何给子实体应用SoftDeletable软删除过滤规则
问题根因
该现象是Gedmo SoftDeletable扩展的默认行为:
- 直接查询
Posts实体时,全局注册的SoftDeletable过滤器会自动追加deletedAt IS NULL条件,因此已软删除数据会被正常过滤 - 通过
Users实体关联加载Posts时,默认的懒加载/预加载逻辑不会自动关联应用关联实体的过滤器,导致已软删除的帖子也会被返回。
解决方案
方案1:全局开启关联过滤(推荐)
如果你希望所有关联查询都自动应用软删除规则,直接修改Doctrine过滤器配置即可。
Symfony框架下修改config/packages/doctrine.yaml:
doctrine: orm: filters: softdeleteable: class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter enabled: true
原生Doctrine项目初始化EntityManager时添加配置:
$config = Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration($paths, $isDevMode); $em = EntityManager::create($dbParams, $config); $em->getConfiguration()->addFilter('softdeleteable', \Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter::class); $em->getFilters()->enable('softdeleteable');
该配置在Gedmo SoftDeletable v2.4及以上版本生效,无需额外配置即可自动作用于所有带软删除字段的关联实体。
方案2:手动在查询中添加过滤条件
如果仅需要在本次查询中过滤软删除帖子,无需全局修改,可以通过QueryBuilder手动关联查询:
return $this->em->getRepository(Users::class) ->createQueryBuilder('u') ->leftJoin('u.posts', 'p', 'WITH', 'p.deletedAt IS NULL') ->addSelect('p') // 预加载帖子,避免后续懒加载带出软删除数据 ->where('u.id = :userId') ->setParameter('userId', $userId) ->getQuery() ->getOneOrNullResult();
方案3:在关联属性上绑定过滤器
如果希望仅Users和Posts的关联查询应用软删除过滤,其他关联不受影响,可以直接在Users实体的posts关联属性上添加Filter注解:
// App\Entity\Users.php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Users { // 其他属性 /** * @ORM\OneToMany(targetEntity=Posts::class, mappedBy="user") * @ORM\Filter(name="softdeleteable") */ private $posts; // 其他方法 }
注意事项
如果修改配置后依然能查询到已软删除的帖子,大概率是EntityManager的一级缓存已经缓存了之前加载的关联数据,调用$em->refresh($user)刷新实体即可解决。
内容的提问来源于stack exchange,提问作者Fares Karbia
相关产品推荐
相关产品推荐

