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

Laravel 5.5中如何对Api Resources的JSON响应进行分组?

在Laravel 5.5中对API Resources返回的JSON按年/月分组

我来一步步帮你实现按年月分组并格式化API响应的需求:

1. 先处理数据库查询(合并同年月的人员数据)

首先要从数据库层面把相同年份和月份的人员数据合并,还要去掉重复的名字(比如你例子里的「中島 春香」出现了两次)。假设你的模型是PeopleRecord,对应数据表为people_records,可以这么写查询:

use Illuminate\Support\Facades\DB;

$records = DB::table('people_records')
    ->select(
        'year',
        'month',
        DB::raw('GROUP_CONCAT(DISTINCT people SEPARATOR ", ") as merged_people')
    )
    ->groupBy('year', 'month')
    ->orderBy('year', 'desc')
    ->orderBy('month', 'desc')
    ->get();

这里用GROUP_CONCAT(DISTINCT ...)完成人员名字的合并与去重,同时按年月降序排列,让最新的数据排在前面。

2. 创建API资源类

接下来创建资源类来格式化单条记录,先执行命令生成资源:

php artisan make:resource PeopleRecordResource

然后修改app/Http/Resources/PeopleRecordResource.php的toArray方法,把合并后的字符串转成数组(更符合API的规范格式):

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PeopleRecordResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'year' => $this->year,
            'month' => $this->month,
            'people' => explode(', ', $this->merged_people)
        ];
    }
}

如果需要进一步按年份嵌套分组(把同一年的所有月份数据放在一起),可以再创建一个集合资源类YearGroupedPeopleResource:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class YearGroupedPeopleResource extends ResourceCollection
{
    public function toArray($request)
    {
        // 先按年份分组
        $grouped = $this->collection->groupBy('year');
        
        // 格式化每个年份下的月份数据
        return $grouped->map(function ($monthRecords, $year) {
            return [
                'year' => $year,
                'months' => PeopleRecordResource::collection($monthRecords)
            ];
        })->values()->all();
    }
}

3. 在控制器中返回分组后的响应

根据你的需求选择不同的返回方式:

选项1:仅按年月平级分组

use App\Http\Resources\PeopleRecordResource;

public function index()
{
    $records = DB::table('people_records')
        ->select(
            'year',
            'month',
            DB::raw('GROUP_CONCAT(DISTINCT people SEPARATOR ", ") as merged_people')
        )
        ->groupBy('year', 'month')
        ->orderBy('year', 'desc')
        ->orderBy('month', 'desc')
        ->get();

    return PeopleRecordResource::collection($records);
}

返回的JSON格式示例:

[
    {
        "year": 2017,
        "month": 11,
        "people": ["..."]
    },
    {
        "year": 2017,
        "month": 3,
        "people": ["松本 知実", "桐山 裕太", "吉本 稔", "藤本 稔"]
    },
    // 其他记录
]

选项2:按年份嵌套分组

use App\Http\Resources\YearGroupedPeopleResource;

public function index()
{
    $records = DB::table('people_records')
        ->select(
            'year',
            'month',
            DB::raw('GROUP_CONCAT(DISTINCT people SEPARATOR ", ") as merged_people')
        )
        ->groupBy('year', 'month')
        ->orderBy('year', 'desc')
        ->orderBy('month', 'desc')
        ->get();

    return new YearGroupedPeopleResource($records);
}

返回的JSON格式示例:

[
    {
        "year": 2017,
        "months": [
            {
                "year": 2017,
                "month": 11,
                "people": ["..."]
            },
            {
                "year": 2017,
                "month": 3,
                "people": ["松本 知実", "桐山 裕太", "吉本 稔", "藤本 稔"]
            }
        ]
    },
    {
        "year": 2016,
        "months": [
            {
                "year": 2016,
                "month": 12,
                "people": ["中島 春香", "中津川 充", "村山 裕樹", "杉山 翼", "木村 稔"]
            }
        ]
    },
    // 其他年份
]

小提示

  • 如果你的people字段原本就是逗号分隔的字符串,GROUP_CONCAT会自动合并后再用逗号分隔,DISTINCT参数能有效去掉重复的名字。
  • 以上写法完全适配Laravel 5.5版本的API Resources特性,不需要额外扩展。

内容的提问来源于stack exchange,提问作者Ryutaro Matsumoto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:58:44