Laravel Eloquent:如何在Booking模型中获取positions->areas->scopes数据
实现Booking模型直接关联获取Scopes数据
先梳理并补全基础关联
首先确保各模型的基础关联定义正确,对应你的多对多中间表结构:
Position 模型
// 与 Area 多对多关联,中间表 position_areas public function areas() { return $this->belongsToMany(Area::class, 'position_areas'); } // 关联所属 Booking(假设一个 Position 对应一个 Booking) public function booking() { return $this->belongsTo(Booking::class); }
Area 模型
// 与 Position 多对多关联 public function positions() { return $this->belongsToMany(Position::class, 'position_areas'); } // 与 Scope 多对多关联,中间表 area_scopes public function scopes() { return $this->belongsToMany(Scope::class, 'area_scopes'); }
Booking 模型
先定义与 Position 的基础关联:
// 一个 Booking 拥有多个 Position public function positions() { return $this->hasMany(Position::class); }
实现直接加载 Scopes 的两种方式
根据你的 Laravel 版本选择对应方案:
方案一:Laravel 9+ 推荐使用 through 多层关联
Laravel 9 及以上支持通过 through 直接定义跨多层多对多的关联,代码最简洁:
public function scopes() { return $this->belongsToMany(Scope::class)->through([Position::class, Area::class]); }
定义完成后,直接执行 $booking->load('scopes') 就能获取所有关联的 Scope 数据,也可以直接访问 $booking->scopes 拿到集合。
方案二:兼容 Laravel 8 及以下版本
通过自定义关联查询或访问器实现:
方式1:自定义关联查询
public function scopes() { return Scope::query() ->join('area_scopes', 'area_scopes.scope_id', '=', 'scopes.id') ->join('areas', 'areas.id', '=', 'area_scopes.area_id') ->join('position_areas', 'position_areas.area_id', '=', 'areas.id') ->join('positions', 'positions.id', '=', 'position_areas.position_id') ->where('positions.booking_id', $this->id) ->select('scopes.*') ->distinct(); // 去重,避免同一 Scope 重复返回 }
方式2:访问器实现惰性加载
public function getScopesAttribute() { return $this->positions->flatMap(function ($position) { return $position->areas->flatMap(function ($area) { return $area->scopes; }); })->unique('id'); }
这种方式需要先预加载嵌套关联避免重复查询:
$booking->load('positions.areas.scopes'); // 之后直接访问 $booking->scopes 即可
常见排查点
- 确认中间表字段:
position_areas需包含position_id、area_id;area_scopes需包含area_id、scope_id,字段类型与对应模型主键一致。 - 模型主键非
id时,需在模型中指定protected $primaryKey = '你的主键名'。 - 出现重复数据时,记得添加
distinct()或unique('id')去重。
内容的提问来源于stack exchange,提问作者23nr1
相关产品推荐
相关产品推荐

