@geyurgfuyewgfyuguy

Laravel Relationships, не использовать left join, как заменить?

Всем привет, подскажите по такому вопросу.

Есть таблица, постов, у нее есть поле user_id, как получать инфу о юзере с помощью связей, не используя leftJoin.

Если ставлю так:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class, 'id');
}


То он мне делает 20 запросов, при выводе 20 постов, а должен быть один по идее.

Вывод постов

$posts = Post::orderBy('created_at', 'desc')->limit(20)->get();

foreach( $posts as $post )
{
  print_r($post->user);
}
  • Вопрос задан
  • 101 просмотр
Решения вопроса 1
neuotq
@neuotq
Прокрастинация
Это классическая проблема N+1 запроса: при обращении к БД делаем лишних N запросов, хотя можно обойтись одним сразу.
В Laravel она возникает из-за ленивой загрузки отношений по умолчанию, те при выборке данных модели из БД, отношения не выбираются. Чтобы этого избежать используется with (и его "друзья").
//Выбрали все посты, данные только по ним
$posts = Post::orderBy('created_at', 'desc')->limit(20)->get();
foreach( $posts as $post )
{
//обращение к БД за данными по отношению user
  print_r($post->user);
}

//Два запроса
// 1.Выбрали все посты, данные только по ним
// 2. ПО айдишкам из данных таблицы постов, выбрали сразу все нужные из user
$posts = Post::orderBy('created_at', 'desc')->with('user')->limit(20)->get();
foreach( $posts as $post )
{
//обращение к БД за данными по отношению user НЕ происходит, данные уже есть и скомпонованы
  print_r($post->user);
}

Советую читать документацию,
так же самые распространенные подводные камни с N+1 https://laravel-news.com/laravel-n1-query-problems
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@a0xh
$posts = Post::query()->with(['user' => function($query) {
    $query->oldest('created_at')->take(20);
}])->get();

foreach ($posts as $post)
{
    dump($post->user);
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы