doctrine软删除需同时配置filter启用和实体注解,缺一不可:yaml中开启softdeleteable及filter注册,实体类上正确使用@gedmo\softdeleteable()注解并配fieldname字段,子实体需单独配置,绕过软删须禁用filter并清缓存。

Doctrine软删除不是简单加个注解就完事,得配对启用过滤器和实体注解,两者缺一不可。只装包不启 filter,删了查不到;只写注解不配 filter,还是硬删。
必须同时开启 softdeleteable filter
filter 不是自动打开的,得手动配置:
- 在 config/packages/stof_doctrine_extensions.yaml 中确保有:
softdeleteable: true - 在 config/packages/doctrine.yaml 的
doctrine.orm.filters下注册并启用:
soft-deleteable: { class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter, enabled: true } - 启用后,所有
find*、findBy、DQL 查询默认跳过deletedAt IS NOT NULL的记录
@Gedmo\SoftDeleteable() 注解要写对位置和字段
注解必须放在实体类声明上方,不能贴在字段上:
- 错误写法(无效):
/** @Gedmo\SoftDeleteable(fieldName="deletedAt") */ private $deletedAt; - 正确写法:
/** * @ORM\Entity * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=true, hardDelete=false) */ class Article { ... } -
fieldName必须对应一个@ORM\Column(type="datetime", nullable=true)字段 -
hardDelete=false是关键——它让$em->remove($entity)只更新deletedAt,不执行 SQL DELETE
集合表单(CollectionType)里的子项要单独处理
父实体加了软删除,子实体不会自动软删:
- 每个子实体类自己也得加上
@Gedmo\SoftDeleteable()注解 - 关联映射中避免用
cascade={"remove"},改用cascade={"persist"},再手动调用子项的remove() - 表单提交时,
allow_delete: true触发的$collection->removeElement($child)不会自动设$child->setDeletedAt(),需在PreRemove事件或表单处理后手动赋值
绕过软删除查/删数据要清缓存+关 filter
想查已软删记录或真删某条数据(如归档清理),光禁用 filter 不够:
- 先调用
$em->getFilters()->disable('soft-deleteable') - 再清除 EntityManager 缓存:
$em->clear(),否则可能命中旧查询结果 - 如需物理删除,可临时设
hardDelete=true,或直接执行原生 SQL











