查不到软删除数据主因是软删除未生效:检查deleted_at字段是否存在且为timestamp/datetime类型、模型是否正确引入softdeletes trait、数据是否真正执行了delete()而非手动更新或硬删除。

查不到已软删除的数据,大概率不是 onlyTrashed() 本身出错,而是前置条件没满足——软删除根本就没生效,或者数据压根没被软删过。
检查 deleted_at 字段是否存在且类型正确
数据库表里必须有 deleted_at 字段,类型为 TIMESTAMP 或 DATETIME(不能是 TINYINT、INT 或字符串模拟)。Laravel 的 whereNull('deleted_at') 在非时间类型上行为不可靠,会导致全局作用域失效。
- 用
php artisan tinker查一下:User::first()->getAttributes()看有没有deleted_at键 - 执行 SQL:
DESCRIBE users;确认字段存在、可空、类型是 timestamp/datetime - 如果字段缺失,补迁移:
$table->softDeletes();或显式写$table->timestamp('deleted_at')->nullable();
确认模型正确引入 SoftDeletes trait
只加字段不加 trait,delete() 还是硬删除;只加 trait 不加字段,调用 delete() 会报错或静默失败。
- 模型中必须有:
use Illuminate\Database\Eloquent\SoftDeletes;和use SoftDeletes; - 检查是否拼写错误,比如写成
SoftDelete(少 s)或softDeletes(小写) - trait 必须在
class User extends Model内部使用,不能放在外部或条件块里
验证数据是否真被软删除了
onlyTrashed() 只找 deleted_at IS NOT NULL 的记录。如果数据是手动 update 设置的 deleted_at,或通过硬删除(forceDelete())、原生 SQL 删除的,它不会被查到。
- 直接查库:
SELECT * FROM users WHERE deleted_at IS NOT NULL LIMIT 5; - 确认你删的是这条记录:
$user = User::find(123); $user->delete();—— 这才触发软删 - 别混淆
destroy()和delete():批量destroy()默认也走软删,但前提是模型启用了 trait 且字段存在
排除查询链干扰和缓存影响
onlyTrashed() 只作用于当前查询链,不改变后续操作;Eloquent 查询缓存或应用层缓存也可能返回旧结果。
- 写死测试:
User::onlyTrashed()->count(),看是否为 0;再试User::withTrashed()->count(),对比总数 - 临时关掉缓存:
php artisan config:clear && php artisan cache:clear - 避免链式误用:比如
User::where('id', 1)->onlyTrashed()->first()是错的——where先执行,已过滤掉软删行,onlyTrashed()后加也没用;应写成User::onlyTrashed()->where('id', 1)->first()











