Yii框架中删除记录默认不更新时间戳,可通过重写beforeDelete()实现软删除并自动写入deleted_at字段,或使用yii2-soft-delete扩展统一管理,查询时默认排除已删除记录。

Yii框架中删除记录时默认不会自动更新时间戳,但可以通过重写模型的 beforeDelete() 方法,配合数据库字段(如 deleted_at)实现“软删除”并自动记录删除时间。
启用软删除并自动写入 deleted_at
在模型中定义一个表示删除时间的字段(如 deleted_at),并重写 beforeDelete() 方法,将当前时间写入该字段,再返回 false 阻止物理删除:
- 确保数据库表中存在
deleted_at字段(类型为DATETIME或TIMESTAMP,允许 NULL) - 在模型类中添加如下逻辑:
public function beforeDelete()
{
if (parent::beforeDelete()) {
$this->deleted_at = date('Y-m-d H:i:s');
$this->update(false, ['deleted_at']);
return false; // 阻止实际 DELETE
}
return false;
}
这样调用 $model->delete() 实际执行的是软删除,并自动填充删除时间。
配合 yii2-soft-delete 扩展简化处理
使用社区扩展 yii2-soft-delete 可以统一管理软删除行为:
- 安装扩展:
composer require creocoder/yii2-soft-delete - 在模型中引入行为并配置:
use creocoder\softdelete\SoftDeleteBehavior;
public function behaviors()
{
return [
'softDeleteBehavior' => [
'class' => SoftDeleteBehavior::class,
'softDeleteAttributeValues' => [
'deleted_at' => date('Y-m-d H:i:s'),
],
],
];
}
该行为会自动拦截 delete(),更新指定字段,并修改查询默认添加 WHERE deleted_at IS NULL 条件。
查询时自动排除已删除记录
若未使用扩展,需手动在查询中过滤已删除数据:
- 重写模型的
find()方法,让默认查询不包含软删除记录:
public static function find()
{
return parent::find()->where(['deleted_at' => null]);
}
如需查出所有记录(含已删除),可调用 static::find()->withDeleted()->all(),前提是已按扩展方式或自定义方式实现了 withDeleted() 方法。
硬删除时也想记录删除时间?谨慎使用
若业务要求物理删除前仍要留痕(如审计日志),不应在 beforeDelete() 中修改当前模型字段(因后续不会保存),而应:
- 在
beforeDelete()中单独插入一条日志记录到审计表 - 或使用数据库触发器,在执行
DELETE前写入时间戳到另一张表 - 避免在软删除逻辑外强行做硬删+打标,易导致数据不一致
真正需要硬删的场景,建议另起方法如 forceDelete() 显式调用,并在其中完成日志写入和物理删除。


















