如何使用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
相关产品推荐
相关产品推荐

