Laravel - Eager Загрузка - PullRequest
       16

Laravel - Eager Загрузка

0 голосов
/ 29 января 2019

Я пытаюсь понять Eager Loading, используя Laravel, чтобы избежать генерации большого количества ненужных запросов.Я хочу получить 15 последних добавленных сообщений, а также получить их оценки из зависимости от моей таблицы ставок (до того, как я получил сообщения, а затем в foreach я вызывал $ item-> avgRate (), который создает 15 дополнительных запросов: S).

Модель My Post:

public function rates()
{
    return $this->hasMany(Rate::class);
}

public function scopeLastAdded($query, $limit = 15)
{
    return $query->latest()->limit($limit)->with('rates')->get();
}

Это работает, для каждого поста я также получаю все оценки, но главная цель - сделать некоторую функцию для вычисления средней оценки для каждого поста ине восстановить все ставки.Я создал новый метод:

public function avgRate()
{
    return number_format($this->rates()->avg('rate'), 1, '.', '');
}

Когда я использую with('avgRate') моя модель не работает:

Вызов функции-члена addEagerConstraints () для строки

Как я могу получить avgRate каким-то чистым способом с моими последними 15 сообщениями для выполнения только 2 запросов, а не 16?

Ожидаемый результат:

// Post view
@foreach ($posts as $post)
   <div>{{ $post->title }}</div>
   <div>{{ $post->avgRate }}</div> //I want to get data without performing 15 queries
@endforeach

1 Ответ

0 голосов
/ 29 января 2019

Я бы использовал подзапрос для достижения этой цели.Кроме того, чтобы сделать вещи немного чище, вы можете создать область для получения рейтинга:

public function scopeWithRating($query)
{
    $rating = Rate::selectRaw('AVG(rate)')
        ->whereColumn('post_id', 'posts.id')
        ->getQuery();

    $query->select('posts.*')
        ->selectSub($rating, 'rating');
}

... и использовать его, вы должны сделать:

Post::withRating()->get(); 

Теперь ваши Post объекты также будут содержать столбец rating, и это было сделано, по сути, с помощью одного запроса.

Вот пример , чтобы проиллюстрировать это.

...