Я пытаюсь понять Eager Loading с помощью Laravel, чтобы не создавать много ненужных запросов. Я хочу получить 15 последних добавленных сообщений, а также получить их оценки из отношения моей таблицы ставок (до того, как я получал сообщения, а позже в foreach я вызывал $item->avgRate(), который создает 15 дополнительных запросов: S).
Моя модель поста:
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'), моя модель дает сбой:
Call to a member function addEagerConstraints() on string
Как я могу получить 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






Я бы использовал подзапрос для достижения этой цели. Кроме того, чтобы сделать вещи немного чище, вы можете создать область для получения рейтинга:
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, и это было сделано, по сути, с помощью одного запроса.
Вот пример, чтобы проиллюстрировать это.
Спасибо, @Mozammil, мне нравится твоя идея, кажется ясной. Попробую!