Laravel 5.3-加载关系时的多个db查询
我有Laravel 5.3-加载关系时的多个db查询,laravel,query-optimization,laravel-5.3,Laravel,Query Optimization,Laravel 5.3,我有posts表(id,user\u id,title)和Post模型,其中包含此内容 class Post extends Model { public function user() { return $this->belongsTo('App\User'); } } 我想通过id和用户信息获取一些帖子,所以我使用这个查询 $post = new Post(); $res = $post->where('id', 1)->sele
posts
表(id,user\u id,title)和Post
模型,其中包含此内容
class Post extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
我想通过id和用户信息获取一些帖子,所以我使用这个查询
$post = new Post();
$res = $post->where('id', 1)->select('id', 'title', 'user_id')->with([
'user' => function ($query) {
$query->select('id', 'name', 'email');
}
])->first();
它按预期返回数据,我可以访问帖子的信息,如$res->title
,或用户信息,如$res->user->email
,但问题是它对数据库进行了两次查询
我希望只有一个问题
SELECT
`posts`.`id`,
`posts`.`title`,
`posts`.`user_id`,
`users`.`id`,
`users`.`email`,
`users`.`name`
FROM
`posts`
LEFT JOIN `users`
ON `posts`.`user_id` = `users`.`id`
WHERE `posts`.`id` = '1'
LIMIT 1
请注意,这与N+1
问题不同
我知道我可以手动进行左连接
$res = $post->where('posts.id', 1)
->select('posts.id', 'posts.title', 'posts.user_id', 'users.email', 'users.name')
->leftJoin('users', 'posts.user_id', '=', 'users.id')
->first();
它将有我需要的一个查询,但问题是结果中相关表中的所有数据都在同一个数组中(此外,如果每次都必须手动进行左联接,那么定义/使用关系有什么意义)
因此,我的问题是如何通过一个查询获得具有相关表的post数据,并根据关系组织结果:我很好奇laravel的最佳实践是什么,以及有经验的laravel开发人员是如何做到这一点的
谢谢
您正在使用
->with([
'user' => function ($query) {
$query->select('id', 'name', 'email');
}
])
在即时加载中,首先在查询上方运行,并获取与查询匹配的所有用户
然后将结果应用于外部查询,该查询是
$post->where('id', 1)->select('id', 'title', 'user_id')->with([
'user' => function ($query) {
$query->select('id', 'name', 'email');
}
])->first();
Eloquent从不使用连接来检索关系数据,而是在PHP对象中使用单独的查询并将数据链接在一起。因此,对于每个关系,您将始终有一个额外的查询。此外,Elounce主要加载所有列(使用
*
)
要将它们链接在一起,您必须停止使用查询生成器,而是直接使用Eloquent:
$post = Post::find(1)->load('user');
如果您坚持使用联接,则必须继续使用查询生成器。谢谢您的回复,但我不知道它如何回答问题来回答您的问题:使用foreach语句。如果不想使用关系,而是使用连接,则需要自己编写逻辑。我不建议走这条路,使用关系,有2个查询和轻松的生活。
“轻松的生活”
?,一开始可能很容易,如果你有大型项目和高流量的网站,你将不得不使用10倍以上的资源,实际上,有一个大型项目和更多的流量,急切的加载是非常有用的。如果您foreach()
您的查询将面临N+1问题。但是由于有这么多的流量和急切的加载,你仍然只需要花费两个需求。@dav这个答案有用吗?