Laravel 5.3 - 加载关系时的多个db查询

时间:2017-02-03 10:46:21

标签: laravel query-optimization laravel-5.3

我有posts表(id,user_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,但问题是它是2查询数据库

laravel queries with relations

我希望只有一个查询

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问题不同 https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

我知道我可以手动进行左连接,

$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();

它会有我需要的一个查询,但问题是在结果中来自相关表的所有数据都在同一个数组中(此外,如果我必须手动制作,定义/使用关系的重点是什么每次左连接)

enter image description here

所以,我的问题是如何使用一个查询获得相关表格的帖子数据,并根据关系组织结果:我很好奇laravel中的最佳实践以及经验丰富的Laravel开发人员是如何做到这一点的?

由于

2 个答案:

答案 0 :(得分:1)

那是eager loading

您正在使用

->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();

答案 1 :(得分:1)

Eloquent从不使用JOIN来检索关系数据,而是使用单独的查询并将数据链接在PHP对象中。因此,对于每个关系,您将始终有一个额外的查询。此外,Eloquent主要加载所有列(使用*)。

要将它们链接在一起,您必须停止使用查询构建器,而是直接使用Eloquent:

$post = Post::find(1)->load('user');

如果您坚持使用JOIN,则必须继续使用查询构建器。