
Laravel 的 whereBetween 默认按精确时间比较,若未指定时间部分,'2022-06-19' 会被解释为 '2022-06-19 00:00:00',导致同日但晚于零点的记录(如 '2022-06-19 14:30:00')被遗漏。
laravel 的 `wherebetween` 默认按精确时间比较,若未指定时间部分,`'2022-06-19'` 会被解释为 `'2022-06-19 00:00:00'`,导致同日但晚于零点的记录(如 `'2022-06-19 14:30:00'`)被遗漏。
在 Laravel 中使用 whereBetween('created_at', [$from, $to]) 进行日期范围查询时,常见误区是直接传入字符串格式的日期(如 '2022-06-18' 和 '2022-06-19')。由于数据库字段 created_at 是 DATETIME 类型,Laravel 和底层数据库会将 '2022-06-19' 自动解析为 '2022-06-19 00:00:00'。因此,order2(创建于 '2022-06-19 15:22:10')不满足 created_at <= '2022-06-19 00:00:00',从而被排除。
✅ 正确做法:将结束日期扩展至当日最后一秒,或使用 whereDate 配合 >= / <= 精确控制日期边界:
方案一(推荐):使用 whereDate —— 语义清晰、无时区歧义
use Illuminate\Support\Facades\DB;
$orders = DB::table('orders')
->whereDate('created_at', '>=', $from_date) // 2022-06-18 → 匹配所有该日起的记录
->whereDate('created_at', '<=', $to_date) // 2022-06-19 → 匹配所有该日止的记录
->get();方案二:手动构造完整时间范围
$startDate = \Carbon\Carbon::parse($from_date)->startOfDay(); // 2022-06-18 00:00:00
$endDate = \Carbon\Carbon::parse($to_date)->endOfDay(); // 2022-06-19 23:59:59
$orders = DB::table('orders')
->whereBetween('created_at', [$startDate, $endDate])
->get();⚠️ 注意事项:
- 避免直接拼接字符串日期(如 "'$from_date'"),易引发 SQL 注入与类型不匹配;
- 若 $from_date 和 $to_date 来自用户输入,务必通过 Carbon::parse() 或 date('Y-m-d') 校验格式;
- 使用 Eloquent 模型时,可进一步封装为作用域(Scope)提升复用性;
- 时区敏感场景下,建议统一配置 app.timezone 并在查询前显式设置 Carbon 时区。
总结:whereBetween 本身无缺陷,问题根源在于日期粒度与 DATETIME 字段的隐式转换。优先选用 whereDate 实现纯日期范围筛选,逻辑更健壮、代码更可读。


















