Laravel如何将多对多关联的指定列数据以数组形式挂载到另一表每一行中
Laravel Eloquent 多对多关联查询解决方案
步骤1:定义模型关联
首先创建对应两张表的Eloquent模型,手动指定自定义表名和关联外键:
Person 模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Person extends Model { // 绑定自定义表名 protected $table = 'person_table'; // 允许批量赋值字段 protected $fillable = ['name_of_person']; // 定义和技能的多对多关联 public function skills(): BelongsToMany { return $this->belongsToMany( Skill::class, 'your_pivot_table_name', // 此处替换为你实际的中间表名称 'person_table_id', // 中间表关联person_table的外键 'skills_table_id' // 中间表关联skills_table的外键 ); } }
Skill 模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Skill extends Model { protected $table = 'skills_table'; protected $fillable = ['name_of_skill']; // 反向多对多关联,按需定义即可 public function persons(): BelongsToMany { return $this->belongsToMany( Person::class, 'your_pivot_table_name', 'skills_table_id', 'person_table_id' ); } }
步骤2:查询数据并格式化输出
使用预加载避免N+1性能问题,查询后直接格式化得到要求的返回结构:
// 预加载技能关联 $personList = Person::with('skills') ->get() ->map(function ($person) { return [ 'id' => $person->id, 'name' => $person->name_of_person, 'skills' => $person->skills->pluck('name_of_skill')->toArray() ]; }); // Laravel会自动将集合转为符合要求的JSON格式 return $personList;
可选:API 场景用资源类统一格式化
如果是API项目,推荐用Laravel的资源类做返回结构的统一管理:
- 生成资源类
php artisan make:resource PersonResource
- 编辑资源类内容
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class PersonResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name_of_person, 'skills' => $this->skills->pluck('name_of_skill')->toArray() ]; } }
- 调用资源类返回
use App\Http\Resources\PersonResource; $personList = Person::with('skills')->get(); return PersonResource::collection($personList);
注意事项
- 必须使用
with('skills')预加载关联,否则数据量较大时会产生N+1查询问题,严重影响性能 - 关联定义时的中间表名、外键字段必须和实际数据库字段完全一致,否则会出现关联查询为空的问题
内容的提问来源于stack exchange,提问作者Harat
相关产品推荐
相关产品推荐

