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

Laravel三表一对多+多对多Eloquent关联定义及去重查询

解决Laravel中Project关联去重Patches的问题

这个问题我之前也碰到过,嵌套循环导致补丁重复确实头疼!因为你的Version和Patch是多对多关系,同一个补丁绑定多个版本时,嵌套遍历自然会重复输出。而你尝试的hasManyThrough其实不太适配这种中间是多对多的关联场景——它本来是为一对多→一对多的层级关系设计的,比如Project→Version→Bug这种每个Version对应多个Bug的情况,而不是多对多的中间关联。

下面给你两种实用的解决方案,直接在Project模型里定义关联就能解决重复问题:

方案一:利用whereHas关联查询+去重

这种方法最直观,借助你已经定义好的Patch和Version的关联,筛选出所有属于当前项目版本的补丁,再用distinct()去重:

public function patches()
{
    return \App\Patch::whereHas('versions', function ($query) {
        $query->where('projects_id', $this->id);
    })->distinct();
}

方案二:用belongsToMany结合Join关联

这种方式直接通过多对多中间表关联,同时过滤出属于当前项目的版本,确保返回唯一补丁:

public function patches()
{
    return $this->belongsToMany(\App\Patch::class, 'versions_patches', 'versions_id', 'patches_id')
        ->join('versions', 'versions.id', '=', 'versions_patches.versions_id')
        ->where('versions.projects_id', $this->id)
        ->distinct()
        ->select('patches.*'); // 只选择补丁表的字段,避免关联带来的重复字段问题
}

使用方式

定义好关联后,你直接调用$project->patches就能拿到去重后的所有补丁集合了,不用再嵌套循环:

@foreach($project->patches as $patch)
    {{ $patch->something }}
@endforeach

关于groupBy的小提醒

你之前尝试的groupBy('patches.id')在Laravel的严格SQL模式下可能会报错(因为需要所有查询字段都在groupBy里),所以用distinct()是更稳妥的去重方式,它会直接返回唯一的补丁记录。

内容的提问来源于stack exchange,提问作者Antonín Slejška

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:09