
Laravel Eloquent 模型默认启用软删除(SoftDeletes),导致 Model::query() 自动排除 deleted_at IS NOT NULL 的记录,而 DB::table() 原生查询则返回所有物理存在的数据,这是二者结果差异的根本原因。
laravel eloquent 模型默认启用软删除(softdeletes),导致 `model::query()` 自动排除 `deleted_at is not null` 的记录,而 `db::table()` 原生查询则返回所有物理存在的数据,这是二者结果差异的根本原因。
在 Laravel 开发中,当你发现使用 DB::table('attendances') 能查到数据,而 Attendance::class 模型查询却返回空集合时,几乎可以确定是软删除(Soft Deletes)在起作用。
Eloquent 模型若使用了 use SoftDeletes; 特性(并已在数据库表中添加 deleted_at 字段),所有常规查询(包括 select()、where()、get() 等)都会自动追加约束条件:
WHERE deleted_at IS NULL
这意味着:即使记录物理上仍存在于数据库中,只要 deleted_at 不为 NULL,Eloquent 就会将其“逻辑隐藏”——这正是你遇到 withModel: [] 而 withDB 正常返回多条记录的原因。
✅ 验证与调试方法
-
检查模型是否启用了软删除
查看 Attendance.php 模型文件:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; // ← 关键 trait class Attendance extends Model { use SoftDeletes; // ← 若存在此行,则软删除已启用 } -
检查数据库表结构
确认 attendances 表包含 deleted_at 字段(通常为 TIMESTAMP NULL):DESCRIBE attendances; -- 应看到类似:deleted_at | timestamp | YES | NULL | NULL |
-
手动查询验证软删除状态
在 Tinker 或路由中执行:// 查看被软删除的记录(Eloquent 默认不显示) Attendance::withTrashed() ->whereIn('attendance_date_id', [925, 926]) ->select('id', 'attendance_date_id', 'remarks', 'deleted_at') ->get();输出将包含 deleted_at 非空的记录——这与 DB::table() 的结果完全对应。
?️ 根据业务需求选择查询策略
| 场景 | 推荐方式 | 示例 |
|---|---|---|
| 仅需有效数据(默认行为) | 直接使用模型查询 | Attendance::where(...)->get() |
| 需包含已软删除的数据 | 使用 withTrashed() | Attendance::withTrashed()->where(...)->get() |
| 仅查已被软删除的数据 | 使用 onlyTrashed() | Attendance::onlyTrashed()->where(...)->get() |
| 彻底物理删除(慎用) | 使用 forceDelete() | $attendance->forceDelete() |
⚠️ 注意:restore() 可恢复软删除记录;delete() 调用的是软删除;若需物理删除,请确认业务无误后再执行 forceDelete() 或 ::where(...)->forceDelete()。
? 补充说明:select() 不影响软删除行为
正如问题中所观察——无论是否调用 select("id","attendance_date_id","remarks"),模型查询结果始终为空。这是因为软删除过滤发生在查询构建阶段早期,独立于字段选择逻辑。Eloquent 总是在 WHERE 子句中注入 deleted_at IS NULL,与 SELECT 列表无关。
掌握这一机制,不仅能快速定位此类“数据消失”问题,更能合理设计数据生命周期管理策略:软删除保障数据安全与可追溯性,而原生查询则提供底层数据可见性——二者不是缺陷,而是 Laravel 分层抽象的精妙体现。










