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

Laravel Eloquent课程双向关联查询问题求助

解决Laravel Eloquent双向关联查询问题

看起来你遇到的是无向自关联多对多的查询问题——你的relatedCourses中间表存储的是课程间的双向关联,但当前的关联方法只处理了从course1到course2的单向查询,所以反过来从course2查course1就失效了。

下面是两种可靠的解决方案,你可以根据自己的需求选择:


方案1:修改关联方法支持双向查询(推荐,无需调整查询代码)

直接修改Course模型中的related关联方法,让它同时匹配中间表中当前课程作为course1或course2的记录,并且排除课程自身:

public function related()
{
    return $this->belongsToMany(Course::class, 'relatedCourses')
        ->where(function ($query) {
            // 匹配中间表中当前课程是course1或course2的记录
            $query->where('relatedCourses.course1', $this->id)
                  ->orWhere('relatedCourses.course2', $this->id);
        })
        // 排除课程自身,避免关联到自己
        ->where('courses.id', '!=', $this->id)
        // 去重,防止同一课程被重复关联(如果中间表有重复记录的话)
        ->distinct();
}

注意事项:

  • 这个方法在单个模型查询(比如find(5)或find(7))时完全正常,能双向获取关联课程。
  • 如果需要批量预加载(比如Course::where('isActive', 1)->with('related')->get()),由于Eloquent预加载时是批量查询,$this->id会指向第一个模型的ID,导致结果异常。这种情况下推荐使用方案2。

方案2:拆分关联+访问器合并结果(支持批量预加载)

这个方法通过定义两个单向关联,再用访问器合并结果,完美支持单个查询和批量预加载:

步骤1:在Course模型中定义两个单向关联

// 作为course1关联的课程(原关联逻辑)
public function relatedAsCourse1()
{
    return $this->belongsToMany(Course::class, 'relatedCourses', 'course1', 'course2')
        ->where('isActive', 1); // 和主查询的活跃条件保持一致
}

// 作为course2关联的课程(反向关联逻辑)
public function relatedAsCourse2()
{
    return $this->belongsToMany(Course::class, 'relatedCourses', 'course2', 'course1')
        ->where('isActive', 1);
}

步骤2:添加访问器合并两个关联的结果

/**
 * 获取双向关联的课程集合
 *
 * @return \Illuminate\Database\Eloquent\Collection
 */
public function getRelatedAttribute()
{
    // 自动加载未预加载的关联
    if (! $this->relationLoaded('relatedAsCourse1')) {
        $this->load('relatedAsCourse1');
    }
    if (! $this->relationLoaded('relatedAsCourse2')) {
        $this->load('relatedAsCourse2');
    }

    // 合并两个集合并去重
    return $this->relatedAsCourse1->merge($this->relatedAsCourse2)->unique('id');
}

步骤3:查询时预加载两个关联

// 单个模型查询
$data["course"] = Course::where("isActive",1)->with(['relatedAsCourse1', 'relatedAsCourse2'])->find(7);

// 批量查询
$courses = Course::where("isActive",1)->with(['relatedAsCourse1', 'relatedAsCourse2'])->get();

现在无论是查ID5还是ID7,都能获取到双向关联的课程了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:35:36