You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:53:10