软删除后查不到数据是因为框架默认过滤掉delete_time非空记录。需检查模型是否正确配置$deleteTime字段、继承Model或使用SoftDelete;查询时用withTrashed()或onlyTrashed();API返回应显式添加is_deleted字段;关联查询需手动启用withTrashed()。

软删除后查不到数据,根本原因不是“删错了”,而是默认查询不包含被软删除的记录。ThinkPHP 的 delete_time 字段标记软删除后,框架会自动过滤掉这些数据——这是设计行为,不是 bug。
确认是否启用软删除机制
先检查模型类是否正确配置了软删除:
- 模型需继承
think\Model(TP6/8)或使用use think\model\concern\SoftDelete; - 必须定义
protected $deleteTime = 'delete_time';(字段名要和数据库一致) - 可选设置
protected $defaultSoftDelete = false;控制默认是否隐藏软删除数据
如果没配或字段名写错(比如写成 deleted_at 但数据库是 delete_time),软删除实际没生效,后续查询逻辑就全乱了。
查不到数据的三种常见场景及解法
直接查全部,包括已软删除的记录
适合回收站、审计日志等场景:
// TP6/8 写法 User::withTrashed()->select(); // 查含软删 + 正常数据 User::onlyTrashed()->select(); // 只查软删数据
注意:withTrashed() 和 onlyTrashed() 是模型方法,不能在 Db 类或原生 SQL 中使用。
立即学习“PHP免费学习笔记(深入)”;
接口中按需恢复或彻底删除
前端点击“还原”时,调用 restore();点“永久删除”时,用 force(true):
// 还原单条
User::where('id', 1)->restore();
// 永久删除(绕过软删,执行真实 DELETE)
User::where('id', 1)->force(true)->delete();API 返回结果需统一处理软删除状态
别让前端猜“这人是不是真没了”。在列表接口里显式返回 is_deleted 字段:
$users = User::field('id,name,email,delete_time')
->select()
->toArray();
foreach ($users as &$user) {
$user['is_deleted'] = !is_null($user['delete_time']);
}
return json(['code' => 200, 'data' => $users]);这样前端能直接用 is_deleted 控制按钮显示(如“还原” or “已删除”灰字)。
关联查询时软删除容易被忽略
比如查用户订单,订单模型也启用了软删除,但主模型没联动处理:
// 错误:只查用户,订单仍走默认过滤 $user->orders; // 订单里软删的不会出现 // 正确:关联时也要带上 withTrashed() $user->orders()->withTrashed()->select();
或者在定义关联关系时就预设:
public function orders()
{
return $this->hasMany(Order::class)->withTrashed();
}不复杂但容易忽略。



















