laravel 13 中用 carbon 实现每日数据查询应避免循环,而通过 db::raw('date(created_at)') 分组聚合、where 限定时间范围确保索引生效,并用 carbon::today() 与 tomorrow() 配合 wherebetween 保证时区一致,再用 carbonperiod 补全缺失日期。

在 Laravel 13 中,使用 Carbon 实现每日数据查询,核心是结合 Eloquent 的时间字段筛选、MySQL 的日期函数(如 DATE())以及 Carbon 提供的精准时间控制能力。关键不在于“写循环查每一天”,而是在单条 SQL 中按天分组聚合,由数据库完成高效统计。
按天分组统计基础写法
假设你要统计用户注册量按天分布,模型为 User,时间字段为 created_at:
- 用
DB::raw('DATE(created_at)')提取日期部分,作为分组依据 - 用
Carbon::now()->subDays(7)动态生成起始时间,避免硬编码 - 必须加
where('created_at', '>=', $start)确保索引可用,不能只依赖GROUP BY
示例代码:
$days = 7;$start = Carbon::now()->subDays($days);
$stats = User::where('created_at', '>=', $start)
->selectRaw('DATE(created_at) as date')
->selectRaw('COUNT(*) as count')
->groupBy('date')
->orderBy('date')
->get();
?>
处理自然日边界与时区一致性
Laravel 默认使用应用配置的时区(app.timezone),但数据库存储建议统一为 UTC。若你发现“今天”的数据漏掉或重复,大概率是时区未对齐:
- 查“今天”数据,用
Carbon::today()和Carbon::tomorrow()配合whereBetween最安全 - 避免用
whereDate('created_at', Carbon::today())—— 它会在 SQL 中调用DATE()函数,可能导致索引失效 - 推荐写法:
whereBetween('created_at', [Carbon::today(), Carbon::tomorrow()])
支持多时间段快捷筛选(如本周、上月)
业务常需“过去7天”“本月”“上个月”等预设范围。Carbon 提供语义化方法直接构造:
- 本周:
Carbon::now()->startOfWeek()到Carbon::now()->endOfWeek() - 本月:
Carbon::now()->startOfMonth()到Carbon::now()->endOfMonth() - 上个月:
Carbon::now()->subMonthNoOverflow()->startOfMonth()到Carbon::now()->subMonthNoOverflow()->endOfMonth()
注意 subMonthNoOverflow() 可防止从 3 月 31 日减一个月变成 2 月 31 日(无效日期)。
补全缺失日期(让图表不缺天)
数据库中某天无数据,查询结果就跳过该日,前端图表可能断层。需手动补零:
- 先查出有数据的日期集合,转为键值对(如
['2026-10-15' => 23]) - 用
CarbonPeriod::create($start, $end)生成完整日期序列 - 遍历该序列,用
?? 0填充缺失值
例如:
$period = CarbonPeriod::create($start, $end);$result = [];
foreach ($period as $date) {
$key = $date->toDateString();
$result[$key] = $rawData[$key] ?? 0;
}











