thinkphp软删除字段名可自定义,关键在于模型中配置$deletetime;支持时间型(如deleted_at)和布尔/整型(如['is_deleted',1])两种类型,需确保迁移文件约束与模型配置一致。

ThinkPHP 的 delete_time 字段不是必须叫这个名字
ThinkPHP 默认启用软删除时,会检查模型是否定义了 delete_time 字段,并自动在查询中过滤掉该字段非空的记录。但这个字段名完全可以自定义——只要你在模型里明确告诉框架用哪个字段做删除标记。
关键不是字段名,而是配置。比如你想用 is_deleted(布尔型)或 deleted_at(时间型),只需在模型类中设置:
protected $softDelete = true; protected $deleteTime = 'deleted_at'; // 或 'is_deleted'
注意:$deleteTime 支持两种类型:
- 字符串(如
'deleted_at'):表示时间戳字段,软删时写入当前时间 - 数组(如
['is_deleted', 1]):表示布尔/整型字段,软删时写入指定值(第二个元素)
用 withTrashed() 和 onlyTrashed() 查出“被删”的数据
默认所有查询(包括 find、select、关联查询)都会自动排除软删记录。想查包含已软删的数据,得显式调用 withTrashed();只查已软删的,用 onlyTrashed()。
常见误操作是以为加个 where('delete_time', null) 就能绕过软删逻辑——不行,框架会在 SQL 生成前就注入过滤条件,手动 where 会被合并或覆盖。
正确写法示例:
// 查全部,含已软删 UserModel::withTrashed()->select(); // 只查已软删的 UserModel::onlyTrashed()->select(); // 软删后恢复(仅对时间型字段有效) UserModel::withTrashed()->find(123)->restore();
软删字段类型选 datetime 还是 tinyint?看你要不要“删的时间”
用 datetime 类型(如 deleted_at)能记录删除发生的具体时间,方便审计、恢复判断、或配合定时任务清理;用 tinyint(如 is_deleted)更省空间、查询略快,但丢失时间维度。
ThinkPHP 对两种类型都支持,但行为有差异:
-
datetime字段:调用delete()会自动写入当前时间;调用restore()会清空该字段 -
tinyint字段:需配成['is_deleted', 1],delete()写入1,restore()写回0(不能为null) - 字段不允许为
NOT NULL DEFAULT NULL——否则restore()会失败(MySQL 报错:Invalid datetime format)
关联模型不会自动继承软删配置
如果你在 UserModel 开启了软删,但它的关联模型 PostModel 没配 $softDelete = true,那么 UserModel::with('posts')->find(1) 仍会查出 PostModel 中已被软删的记录。
这不是 bug,是设计使然:每个模型独立控制自己的查询逻辑。要让关联也过滤软删数据,必须在关联定义里手动加作用域:
public function posts()
{
return $this->hasMany(PostModel::class)->withTrashed(false);
}
或者更稳妥的做法:在 PostModel 自身开启软删,并确保其 $deleteTime 配置与实际字段一致。否则容易出现“用户看着正常,点进详情却看到一堆不该显示的内容”。
最常被忽略的一点:迁移文件里建表时,软删字段的默认值和约束要跟模型配置对齐——比如用了 ['is_deleted', 1],那字段就得是 TINYINT DEFAULT 0,而不是 DEFAULT NULL。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











