Laravel按日期分组时如何补全无数据日期(指定数量)
Laravel补全无数据日期分组的实现方法
问题场景
当前使用以下Laravel查询代码:
DowntimeHistoryMonitoring::whereDate('created_at', '<=', now()) ->get(['id', 'created_at']) ->groupBy(function ($item){ return $item->created_at->format('Y-m-d'); });
返回结果仅包含有数据的日期分组:
{ "2022-11-30": [ { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-30T13:06:42.000000Z" }, { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-30T14:06:42.000000Z" } ], "2022-11-29": [ { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-29T13:06:42.000000Z" } ] }
需要实现:指定天数(例如5天),补全无对应数据的日期并显示空数组,最终输出如下:
{ "2022-11-30": [ { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-30T13:06:42.000000Z" }, { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-30T14:06:42.000000Z" } ], "2022-11-29": [ { "id": "507a3832-c9d3-4baf-b6a8-ff8100c59897", "created_at": "2022-11-29T13:06:42.000000Z" } ], "2022-11-28": [], "2022-11-27": [], "2022-11-26": [] }
实现步骤
通过生成日期范围集合 + 合并已有数据的方式即可实现,具体代码如下:
1. 生成指定天数的日期范围集合
借助Carbon的CarbonPeriod快速生成连续日期范围,以下示例生成最近5天的日期集合:
use Carbon\CarbonPeriod; // 生成从4天前到今天的连续日期(共5天) $datePeriod = CarbonPeriod::create(now()->subDays(4), now()); // 将日期转换为Y-m-d格式的键,值初始化为空数组 $dateRange = collect($datePeriod)->mapWithKeys(function ($date) { return [$date->format('Y-m-d') => []]; });
2. 查询并分组已有数据
保留原有查询逻辑,获取已有数据的日期分组结果:
$existingGroups = DowntimeHistoryMonitoring::whereDate('created_at', '<=', now()) ->get(['id', 'created_at']) ->groupBy(function ($item) { return $item->created_at->format('Y-m-d'); });
3. 合并集合补全无数据日期
使用replace方法将已有数据的分组结果覆盖到日期范围集合中,有数据的日期会替换为空数组,无数据的日期保持空数组:
$finalResult = $dateRange->replace($existingGroups); // 转换为格式化JSON输出 return $finalResult->toJson(JSON_PRETTY_PRINT);
完整代码示例
use Carbon\CarbonPeriod; public function getDowntimeHistory() { // 1. 生成最近5天的日期范围集合 $datePeriod = CarbonPeriod::create(now()->subDays(4), now()); $dateRange = collect($datePeriod)->mapWithKeys(function ($date) { return [$date->format('Y-m-d') => []]; }); // 2. 查询已有数据并分组 $existingGroups = DowntimeHistoryMonitoring::whereDate('created_at', '<=', now()) ->get(['id', 'created_at']) ->groupBy(function ($item) { return $item->created_at->format('Y-m-d'); }); // 3. 合并补全数据 $finalResult = $dateRange->replace($existingGroups); return $finalResult->toJson(JSON_PRETTY_PRINT); }
内容的提问来源于stack exchange,提问作者Lucas Fernandes
相关产品推荐
相关产品推荐

