加入 Eloquent 打破关系?

Posted

技术标签:

【中文标题】加入 Eloquent 打破关系?【英文标题】:Join on Eloquent breaks Relationships? 【发布时间】:2021-08-22 18:15:39 【问题描述】:

我有以下关系:

CourseUsers 之间存在多对多关系,UsersCertificates 之间又存在多对多关系。

现在这里是如何从一个课程中获取所有用户的方法,这些用户在同一课程中拥有证书:

$user = $course->users()
  ->whereHas('certificates', function ($query) use($course)
         $query->where('course_certificates.course_id', '=', $course->id);
)->first();

这将返回具有证书$user->certificates 的用户。 这是查询。

SELECT *
FROM "course_users"
WHERE "course_users"."course_id" = ? AND
    "course_users"."course_id" IS NOT NULL AND
    EXISTS (
        SELECT *
        FROM "course_certificates"
        WHERE "course_users"."id" = "course_certificates"."user_id" AND
        "course_certificates"."course_id" = ?
    )

如果我改用join

$user = $course->users()
    ->join('course_certificates', 'course_certificates.user_id', '=', 'course_users.id')
    ->where('course_certificates.course_id', '=', $course->id)
    ->first();

然后我得到同一个用户,但是$user->certificates 的关系是空的?

SELECT *
FROM "course_users"
INNER JOIN "course_certificates"
    ON "course_certificates"."user_id" = "course_users"."id"
WHERE "course_users"."course_id" = ? AND
    "course_users"."course_id" IS NOT NULL AND
    "course_certificates"."course_id" = ?

这是为什么呢?

【问题讨论】:

我不希望这会有所作为,但如果你渴望通过->with('certificates') 加载certificates 这两个查询,它会改变什么吗?乍一看,我不明白为什么第二种方法对$user->certificates没有任何作用... 我猜第二种方法会将两个表数据合并到关联数组中。但是 laravel 关系以单独的密钥(如证书)返回连接的表数据。第二种方法,例如在 mysql 中执行查询。我希望使用或 whereha 基于表字段进行内部映射并生成用户友好的结果 在第一种情况下,当您不使用 join 时,它是一个 Eloquent 模型。但是当你使用 join 时,它会变成查询生成器,$user->certificates 不起作用。 @TimLewis 我也会尝试从头开始创建这个示例,也许它与我的版本有关,我在 Laravel 5.6 上 不清楚,您编写了 2 个与用户的多名关系,但在课程和证书之间还有一个数据透视表。您能否分享您的测试代码(在 github 上)以完全重现您所做的事情。 【参考方案1】:

我不是 100% 确定,但如果你使用 join,我认为 laravel 不理解你加入的任何表,它是一个关系,它只是一个连接,它可能意味着任何东西,但第一个查询您告诉它关系的含义(whereHas X 关系的一些数据)。


查看源代码,我可以确认我在说什么:joinwhereHas(和 has)。

getRelated() 具有魔力(将数据添加到您的关系中)。看到join 没有做任何事情,它实际上加入了查询,没有其他与关系相关的内容。同样join 来自Query/Builder,任何其他关于关系的方法都来自Eloquent/Builder

【讨论】:

以上是关于加入 Eloquent 打破关系?的主要内容,如果未能解决你的问题,请参考以下文章

无法获取加入多个 Eloquent 关系的数据

Laravel Eloquent关于加入关系的条款

Laravel Eloquent 根据数据透视表字段条件获取多对多关系

如何加入 Eloquent?

Lumen + Eloquent 6.X 加入并聚合成 JSON 结构

雄辩的关系过滤