为什么 "with" 会在 Eloquent 中产生多个查询

How come "with" results in multiple queries in Eloquent

从这里开始:https://laravel-news.com/eloquent-eager-loading

运行 这一行:App\Post::with('author.profile')->get(); 导致执行 3 个查询:

[2017-08-04 07:27:27] local.INFO: select * from `posts`  
[2017-08-04 07:27:27] local.INFO: select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [1,2,3,4,5] 
[2017-08-04 07:27:27] local.INFO: select * from `profiles` where `profiles`.`author_id` in (?, ?, ?, ?, ?) [1,2,3,4,5] 

怎么会? 有没有一种简洁的方法可以在一个查询中执行此操作?

我希望生成的查询类似于:

SELECT * 
FROM posts, authors, profiles 
WHERE posts.author_id = author.id
AND author.profile_id = profiles.id

它仍然比延迟加载好得多,这意味着每个查询都是单独的。

您的期望不会如您所想。您可以改用加入。

像这样:

\DB::table('posts as p')
    ->join('authors as a', 'p.author_id', '=', 'a.id')
    ->join('profiles as pr', 'pr.id', '=', 'a.profile_id')
    ->get();

Eloquent 执行这样的查询,因此它可以为每一行数据混合一个单独的模型。这对于在加载模型后启用其他 Eloquent 功能很重要。通过预加载,数字查询始终是可预测的。 App\Post::with('author.profile')->get(); 将始终执行三个查询,无论帖子、作者或个人资料的数量如何。如果不预先加载,它将 运行 查询数量成倍增加,具体取决于返回的记录数。这是 Eloquent 实施 Active Record 设计模式的结果。

"cleaner" 查询数据的示例本质上是在进行连接。您可以使用联接在一个查询中获取各种关系的所有数据。 Laravel 上下文中的缺点是所有数据都将存在于 Post 模型中,即使它来自三个不同的表。如果您只想快速显示所有数据,这很好,但在尝试操作和更新数据时会变得更加困难。

这更多是关于使用 Active Record 的问题,而不是针对 Eloquent 本身。支持和反对使用活动记录的争论有很多,我不会深入探讨。有关更多信息,我建议您阅读 Active Record(由 Eloquent 使用)、Data Mapper(由 Doctrine 使用)或更一般的 ORM 设计模式。