Laravel如何将两个查询结果合并为一个Collection并传递给Resource文件
解决Laravel中合并每日使用量与总使用量集合的问题
看起来你遇到的问题是直接给Collection实例赋值total属性导致总记录重复,核心原因是这种方式没有正确将总使用量作为全局附加数据,反而可能意外把它加到了每条每日数据里。下面给你两种靠谱的解决方案:
方案一:使用Collection的additional方法添加全局总数据
Laravel的Collection提供了additional方法,专门用来给集合添加序列化时会一起输出的附加数据,不会影响集合内的原有元素。
步骤代码:
// 先确保每日使用量是Collection(如果原方法返回数组,用collect()转换) $dailyUsage = collect($this->getDailyUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id)); // 获取总使用量 $totalUsage = $this->getTotalUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id); // 给每日集合添加全局总数据 $dailyUsage->additional([ 'total_usage' => $totalUsage ]); // 传递给你的Resource集合类 return new UsageCollection($dailyUsage);
对应的Resource集合类示例:
class UsageCollection extends ResourceCollection { public function toArray($request) { return [ // 输出每日数据列表 'daily_usage' => $this->collection->map(function ($item) { return [ 'date' => $item['date'], 'peakPeriod' => $item['peakPeriod'], 'offpeakPeriod' => $item['offpeakPeriod'] ]; }), // 输出全局总数据 'total_usage' => $this->additional['total_usage'] ]; } }
方案二:构造包含双数据的集合(更直观)
如果你希望结构更清晰,可以直接创建一个包含daily_usage和total_usage的关联数组,再转成Collection传递给Resource。
步骤代码:
$dailyUsage = $this->getDailyUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id); $totalUsage = $this->getTotalUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id); // 合并成一个包含双数据的集合 $combinedData = collect([ 'daily_usage' => $dailyUsage, 'total_usage' => $totalUsage ]); // 传递给自定义的Resource类 return new CombinedUsageResource($combinedData);
对应的Resource类示例:
class CombinedUsageResource extends JsonResource { public function toArray($request) { return [ 'daily_usage' => DailyUsageResource::collection($this->daily_usage), 'total_usage' => new TotalUsageResource($this->total_usage) ]; } }
为什么你的原有代码会出问题?
你之前直接给$dailyUsage->total = $totalUsage赋值,Laravel的Collection并不会把这个实例属性当作序列化时的附加数据,反而如果后续你不小心遍历集合时误操作,会把总数据加到每个元素里,导致总记录重复。上面两种方案都能避免这个问题,让总数据只出现一次,同时和每日数据清晰分离。
内容的提问来源于stack exchange,提问作者user2552863
相关产品推荐
相关产品推荐

