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

如何使用Laravel API Resources结合额外查询实现按国家分组的城市数据API响应?

解决Laravel API资源生成嵌套国家-城市结构的问题

我来帮你搞定这个嵌套结构的API响应!核心思路是先把数据按国家分组,再用两层API资源来分别处理国家和城市的格式。下面是具体步骤:

1. 创建城市级别的API资源

首先,我们需要一个资源类来处理单个城市的格式:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class LocationResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'city' => $this->city,
            'latitude' => (string)$this->latitude, // 转成字符串匹配你的示例格式
            'longitude' => (string)$this->longitude
        ];
    }
}

2. 创建国家级别的API资源

接下来,创建一个资源类来处理国家的结构,里面包含该国家的所有城市:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CountryLocationResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'country' => $this->country,
            'locations' => LocationResource::collection($this->locations)
        ];
    }
}

3. 在控制器中处理数据分组并返回资源

现在在控制器里,我们要把原始数据按国家分组,生成符合要求的结构,再用资源返回:

<?php

namespace App\Http\Controllers;

use App\Http\Resources\CountryLocationResource;
use App\Models\Location; // 假设你的模型是Location,对应存储数据的表

class LocationController extends Controller
{
    public function index()
    {
        // 查询所有记录,按国家分组并生成带序号的国家条目
        $groupedData = Location::all()
            ->groupBy('country') // 按国家分组
            ->values() // 转成索引数组,方便生成id
            ->map(function ($locations, $index) {
                return [
                    'id' => $index + 1, // 生成自增的国家id(1,2,3...)
                    'country' => $locations->first()->country, // 取分组里第一个记录的国家名
                    'locations' => $locations // 该国家下的所有城市记录
                ];
            });

        // 返回嵌套的资源集合
        return CountryLocationResource::collection($groupedData);
    }
}

效果说明

这样处理后,你得到的响应就会和你想要的格式完全一致:

  • 每个国家条目有自增的id和国家名称
  • locations数组里包含该国家所有城市的详细信息,格式完全匹配你的示例

注意事项

  • 如果你的数据表字段名和我假设的不同(比如城市字段叫city_name),记得在资源类里对应修改
  • 如果数据量很大,建议用Location::cursor()代替all()来优化性能,避免一次性加载所有数据到内存
  • 如果你需要更稳定的国家id(不依赖查询顺序),可以考虑单独创建国家表并关联,但当前方案在单表场景下是最便捷的

内容的提问来源于stack exchange,提问作者Akmal Arzhang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:42:44