如何在Laravel Resource API中按分类拆分JSON数据
解决方案
一、分组逻辑的实现位置
分组逻辑写在UserResource类中即可——我们是对单个用户的关联数据做结构转换,ResourceCollection仅用于批量资源的顶层包装(比如统一加分页信息),单个资源的字段处理不需要用到它。
二、按topic分组的代码实现
修改UserResource的toArray方法,利用Laravel集合的groupBy方法对预加载的exams分组,再将每组转换为ExamResource集合:
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class UserResource extends JsonResource { public function toArray($request) { // 处理关联的exams,按topic分组 $groupedExams = $this->whenLoaded('exams', function () { return $this->exams->groupBy('topic')->map(function ($exams) { return ExamResource::collection($exams); }); }); return [ 'id' => $this->id, 'name' => $this->name, 'birth_place' => $this->birth_place, 'exams_by_topic' => $groupedExams, // 替换原topic字段,命名更清晰 ]; } }
三、添加分类统计字段aggregates
如果要给每个topic分组加统计信息(比如考试数量、最高分、平均分等),可以在分组时同步生成统计数据。假设exams表有score字段,示例如下:
1. 修改UserResource的分组逻辑
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class UserResource extends JsonResource { public function toArray($request) { $groupedExamsWithStats = $this->whenLoaded('exams', function () { return $this->exams->groupBy('topic')->map(function ($exams) { return [ 'exams' => ExamResource::collection($exams), 'aggregates' => [ 'total_exams' => $exams->count(), 'highest_score' => $exams->max('score'), 'average_score' => round($exams->avg('score'), 2), 'lowest_score' => $exams->min('score'), ] ]; }); }); return [ 'id' => $this->id, 'name' => $this->name, 'birth_place' => $this->birth_place, 'exams_by_topic' => $groupedExamsWithStats, ]; } }
2. 注意事项
- 统计字段可根据业务需求调整,比如不需要分数统计的话,只保留
total_exams即可 whenLoaded方法确保只有当exams关联被预加载时才返回该字段,避免触发N+1查询- 控制器代码无需修改,已经通过
with('exams')预加载了关联数据
四、最终返回的JSON结构示例
{ "id": 1, "name": "张三", "birth_place": "北京", "exams_by_topic": { "mathematics": { "exams": [ { "id": 1, "title": "高一数学期末考", "topic": "mathematics" } ], "aggregates": { "total_exams": 1, "highest_score": 95, "average_score": 95.00, "lowest_score": 95 } }, "physics": { "exams": [ { "id": 2, "title": "高二物理月考", "topic": "physics" } ], "aggregates": { "total_exams": 1, "highest_score": 88, "average_score": 88.00, "lowest_score": 88 } } } }
内容的提问来源于stack exchange,提问作者Data Science
相关产品推荐
相关产品推荐

