Laravel 10 查询近7天每日数据并补零的核心方法是先用PHP生成连续日期数组,再查询聚合数据并以日期为键合并填充0;也可用MySQL 8.0+ CTE生成日期序列左连接补零,需注意时区、字段类型和索引优化。

在 Laravel 10 中查询近 7 天每日数据并补零(即:即使某天无记录,也要返回该日数据为 0),核心思路是「生成连续日期序列」+「左连接或合并补零」。不能只靠数据库 `WHERE date >= ...` 筛选,否则缺失日期会直接消失。
✅ 生成近 7 天日期数组(PHP 侧补零)
最稳妥、兼容性强的方式:先用 PHP 生成 7 天日期列表,再查出真实数据,最后合并填充 0。
- 用 Carbon 快速生成日期范围:
<?php
$dates = collect(Carbon::now()->subDays(6)->toPeriod(7))
->map(fn($d) => $d->format('Y-m-d'))
->values();
// 结果如:['2024-04-01', '2024-04-02', ..., '2024-04-07'] - 查询真实数据(按日期分组聚合):
$stats = Order::whereBetween('created_at', [
Carbon::now()->subDays(6),
Carbon::now()
])
->selectRaw('DATE(created_at) as date, COUNT(*) as count')
->groupBy('date')
->get()
->keyBy('date'); // 转成 ['2024-04-03' => [...], ...] 形式 - 合并补零:
$result = $dates->mapWithKeys(function ($date) use ($stats) {
$item = $stats->get($date, (object)['date' => $date, 'count' => 0]);
return [$date => $item->count];
});
// 返回:['2024-04-01' => 0, '2024-04-02' => 5, ...]
✅ 使用数据库生成日期序列(MySQL 8.0+ / PostgreSQL)
若数据库支持 CTE(如 MySQL 8.0+),可纯 SQL 生成日期并 LEFT JOIN 补零,减少 PHP 处理量。
- MySQL 示例(Laravel 查询构造器中使用 raw):
$rawDates = "WITH RECURSIVE dates AS (
SELECT CURDATE() - INTERVAL 6 DAY AS date
UNION ALL
SELECT DATE_ADD(date, INTERVAL 1 DAY) FROM dates WHERE date )
SELECT d.date, COALESCE(t.count, 0) as count
FROM dates d
LEFT JOIN (
SELECT DATE(created_at) as date, COUNT(*) as count
FROM orders
WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
GROUP BY DATE(created_at)
) t ON d.date = t.date
ORDER BY d.date";
$result = DB::select($rawDates); - Laravel 中建议封装为 DB::select() 或自定义 View(长期项目可建虚拟日期表)
⚠️ 注意事项与常见坑
- 时区问题:确保 Carbon 和数据库时区一致(推荐统一设为 `Asia/Shanghai`),否则 `CURDATE()` 和 `created_at` 可能跨天
-
时间字段类型:`created_at` 是 `datetime`,用
DATE(created_at)提取日期;若字段是 `date` 类型,可直接比较 - 索引优化:在 `created_at` 字段加索引(尤其数据量大时),避免全表扫描
- 空数据边界:`subDays(6)` + `now()` 是严格 7 天(含今天),如需「过去 7 天(不含今天)」,改用 `subDays(7)->subSecond()`
? 扩展:返回标准 API 格式(含日期和数值)
前端常需数组对象格式,例如:[{"date":"2024-04-01","count":0},...]
- 可链式构建:
$data = $dates->map(function ($date) use ($stats) {
$item = $stats->get($date, (object)['count' => 0]);
return ['date' => $date, 'count' => (int)$item->count];
})->values(); - 直接返回 JSON:
return response()->json($data);


















