
本文讲解在 laravel 中如何通过比较 `work_hour_start` 和 `work_hour_end` 字段的大小关系,准确识别跨零点(如 21:00 → 03:00)的工作时段,并正确筛选今日创建且结束时间实际落在次日的数据。
在处理仅含时间(无日期)的业务字段(如 work_hour_start 和 work_hour_end)时,一个常见难点是:当 work_hour_end 小于 work_hour_start(例如 21:00:00 → 03:00:00),逻辑上意味着该时段跨越了午夜,即结束时间属于次日。而 Laravel 的 whereDate() 等日期方法无法直接作用于纯时间字段,因此不能简单用 whereDate('work_hour_end', Carbon::today()) 判断。
✅ 正确思路是:利用时间值本身的数值关系进行逻辑推断
- 同一日内:work_hour_end > work_hour_start(如 11:00 → 15:00)
- 跨日情形:work_hour_end
因此,要查出「今日创建、且工作时段实际延续到次日」的记录,应使用 whereColumn() 进行同行字段比较:
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
$attendance_in = Attendance::where('employee_id', $id)
->whereColumn('work_hour_start', '>=', 'work_hour_end') // 关键:识别跨日
->whereDate('created', Carbon::today())
->first();⚠️ 注意事项:
- whereColumn() 是 Eloquent 提供的列间比较方法,生成 SQL 中的 WHERE work_hour_start >= work_hour_end,高效且安全;
- 确保数据库中 work_hour_start 和 work_hour_end 字段类型为 TIME(而非 VARCHAR),否则字符串比较可能导致意外结果(如 '10:00' > '9:00' 在字典序下为 false);
- 若需进一步获取「跨日结束的实际日期」(如用于展示“结束于明天 03:00”),可在 PHP 层处理:
$endDateTime = $attendance_in->created->copy()->addDay()->setTimeFromTimeString($attendance_in->work_hour_end); // 输出:2024-06-16 03:00:00(假设 created 是 2024-06-15)
? 总结:面对无日期的时间字段,不要强行注入日期逻辑;转而利用时间值的内在顺序性(TIME 类型天然可比),结合 whereColumn() 做精准行内判断,是 Laravel 中处理跨日时段最简洁、可靠的方式。










