Laravel Eloquent BelongsToMany关联:如何获取中间表最新唯一记录?
在Laravel Eloquent中获取BelongsToMany关联的最新唯一Pivot记录
不需要仅通过join实现,用Eloquent关联配合子查询就能完成需求。下面给出两种可行的实现方式:
方式一:通过whereExists筛选最新记录
利用子查询判断当前pivot记录是否是对应state_id和installer_id分组中创建时间最晚的那条:
// State模型中的关联方法 public function installers() { return $this->belongsToMany(Installer::class, 'installer_state') ->withPivot('baseline', 'created_at') // 加载需要的pivot字段 ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('installer_state as latest') ->whereColumn('latest.state_id', 'installer_state.state_id') ->whereColumn('latest.installer_id', 'installer_state.installer_id') ->groupBy('latest.state_id', 'latest.installer_id') ->havingRaw('MAX(latest.created_at) = installer_state.created_at'); }); }
方式二:先获取最新Pivot记录ID再筛选
如果你的中间表ID是自增的(最新记录的ID最大),可以先查询每个分组的最大ID,再通过whereIn筛选:
// State模型中的关联方法 public function installers() { // 子查询获取每个(state_id, installer_id)分组的最新pivot记录ID $latestPivotIds = DB::table('installer_state') ->select(DB::raw('MAX(id) as pivot_id')) ->groupBy('state_id', 'installer_id'); return $this->belongsToMany(Installer::class, 'installer_state') ->withPivot('baseline', 'created_at') ->whereIn('installer_state.id', $latestPivotIds); }
补充说明
- 如果你不想修改默认的
installers关联,可以新增一个专门的关联方法(比如latestInstallers),这样在需要获取最新记录时调用该方法即可。 - 第一种方式不依赖ID自增,完全基于
created_at判断,适用性更广;第二种方式性能略优,但需要确保ID和created_at的顺序一致。
调用方式和你预期的一样:
$state->installers()->get();
此时返回的Installer 1只会关联中间表的ID 2(state1的最新记录)和ID 3(state2的唯一记录)。
内容的提问来源于stack exchange,提问作者Jon Erickson
相关产品推荐
相关产品推荐

