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

Laravel REST API中JsonResource遍历输出多对多genres关联数据

Laravel API 关联体裁返回实现方案

1. 控制器层预加载关联(解决N+1查询问题)

当前控制器直接查询分页数据未预加载genres关联,循环访问关联时会产生N+1性能问题,修改index方法如下:

public function index()
{
    return MovieResource::collection(Movie::with('genres')->paginate());
}

2. 改造MovieResource返回关联数据

不需要手动写foreach遍历关联,Laravel提供了更优雅的处理方式,有两种可选用法:

  • 简单场景直接映射字段
    直接在genres字段处用集合map方法格式化返回数据即可:
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'status' => $this->status,
            'image_path' => url()->to('/images/' . $this->image_path),
            'genres' => $this->genres->map(fn($genre) => [
                'id' => $genre->id,
                'name' => $genre->name
            ])
        ];
    }
    
  • 复用场景使用独立Genre资源(推荐)
    如果后续其他接口也需要返回体裁数据,先执行Artisan命令生成Genre资源类:
    php artisan make:resource GenreResource
    
    修改生成的GenreResource.php的toArray方法:
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name
        ];
    }
    
    再在MovieResource中调用Genre资源集合返回,搭配whenLoaded避免未预加载时触发额外查询:
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'status' => $this->status,
            'image_path' => url()->to('/images/' . $this->image_path),
            'genres' => GenreResource::collection($this->whenLoaded('genres'))
        ];
    }
    

两种写法最终返回的数据结构完全一致,单条电影数据返回格式示例:

{
  "id": 1,
  "name": "星际穿越",
  "status": 1,
  "image_path": "http://your-app-domain/images/interstellar.png",
  "genres": [
    {"id": 2, "name": "科幻"},
    {"id": 5, "name": "剧情"}
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 09:06:18