“ with”如何导致雄辩的多个查询

时间:2019-06-25 20:57:50

标签: laravel eloquent laravel-5.8

从这里: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

2 个答案:

答案 0 :(得分:3)

Eloquent这样执行查询,因此可以为每一行数据合并一个单独的模型。一旦加载模型,这对于启用其他Eloquent功能非常重要。渴望加载时,查询总是可以预测的。 App\Post::with('author.profile')->get();将始终执行三个查询,无论帖子,作者或个人资料的数量如何。不用急于加载,它将根据返回的记录数以指数方式运行更多查询。这是雄辩地实施Active Record设计模式的结果。

查询数据的“更清洁”方法的示例实质上是进行联接。您可以使用联接在一个查询中获取各种关系的所有数据。在Laravel上下文中,这样做的缺点是所有数据都将存在于Post模型中,即使它们来自三个不同的表也是如此。如果您只想快速显示所有数据,那就太好了,但是在尝试操作和更新数据时,变得更加困难。

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

答案 1 :(得分:2)

它仍然比延迟加载要好得多,这意味着分别查询每个查询。

您的期望不会像您所想的那样起作用。您可以改用join。

类似这样的东西:

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