symfony3 中实现软删除的核心是通过 deletedat 字段逻辑标记删除,借助 gedmo 扩展自动过滤查询并支持恢复与彻底删除。

Symfony3 中实现数据库模型的软删除,核心是不真正删除记录,而是通过标记字段(如 deletedAt)来逻辑隐藏数据,并配合 Doctrine 的生命周期回调与查询扩展完成自动过滤。
添加软删除字段到实体
在实体类中增加一个可为空的 DateTime 字段,用于记录删除时间:
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $deletedAt;
<p>public function getDeletedAt(): ?\DateTime
{
return $this->deletedAt;
}</p><p>public function setDeletedAt(?\DateTime $deletedAt): self
{
$this->deletedAt = $deletedAt;
return $this;
}
</p>使用 Doctrine 扩展(推荐方式)
官方推荐使用 Gedmo Doctrine Extensions,它提供开箱即用的软删除支持:
- 安装扩展:
composer require gedmo/doctrine-extensions - 在实体上启用软删除行为:
use Gedmo\Mapping\Annotation as Gedmo; <p>/**</p>
- @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false) */ class Article { // ... }
- 配置 Doctrine(
config.yml)启用扩展:doctrine: orm: mappings: App: type: annotation dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity' is_bundle: false # 启用软删除监听器 doctrine_extensions: soft_deleteable: true
自动过滤已软删除的数据
启用软删除后,Doctrine 默认会在所有 SELECT 查询中自动排除 deletedAt IS NOT NULL 的记录。但需注意:
- 原生 SQL 查询、
createQuery或 DQL 中手动写的WHERE不受自动过滤影响,需显式加条件 - 若需临时查出已删除记录,可用
Repository::createQueryBuilder()并移除默认过滤:$qb = $repo->createQueryBuilder('a'); $qb->where('a.deletedAt IS NULL'); // 显式控制 - 调用
$em->remove($entity)时,扩展会自动设置deletedAt并跳过物理删除
恢复与彻底删除(可选)
软删除不是最终状态,可根据业务需要提供恢复或强制删除功能:
- 恢复:将
deletedAt设为null,再$em->flush() - 彻底删除:禁用软删除监听器,或使用原生 SQL /
Connection执行DELETE语句(慎用) - 批量清理:可通过 Console 命令定期执行物理清理(如超过 90 天的软删除记录)











