'Laravel improve exists() boolean queries with eager loading
I'm trying to get rid of queries that look like this:
SELECT EXISTS(
SELECT *
FROM `ignorings`
WHERE `ignorings`.`user_id` = 80101 AND
`ignorings`.`user_id` IS NOT NULL AND
(`ignorable_id` = 79141)
) AS `exists`
SELECT EXISTS(
SELECT *
FROM `favorites`
WHERE `favorites`.`favorited_id` = 341 AND
`favorites`.`favorited_id` IS NOT NULL AND
`favorites`.`favorited_type` = '' App\Review
'' AND `user_id` = 80101
) AS `exists`
I'm trying to do it by eager loading:
auth()->user()->load(['favorite', 'ignoring']);
Here is my User model:
public function ignoring()
{
return $this->hasMany(Ignoring::class);
}
public function isIgnoring($userId)
{
return $this->ignoring()
->where(['ignorable_id' => $userId])
->exists();
}
Here is my blade file:
@if (! auth()->user() || ! auth()->user()->isIgnoring($review->user->id))
How can I get rid of these queries by eager loading a boolean? I want to load all the auth()->users() ignoring relationships, so to speak.
Solution 1:[1]
Here is what I came up with so far:
In the Controller method:
if (auth()->user()) {
$ignorings = auth()->user()->ignoring()->get();
foreach ($ignorings as $ignoring) {
$ignoringArray[] = $ignoring->ignorable_id;
}
$favoriteReviews = auth()->user()->favorite()->where('favorited_type', 'App\Review')->get();
foreach ($favoriteReviews as $favoriteReview) {
$favoriteReviewArray[] = $favoriteReview->favorited_id;
}
$favoriteReviewComments = auth()->user()->favorite()->where('favorited_type', 'App\ReviewComment')->get();
foreach ($favoriteReviewComments as $favoriteReviewComment) {
$favoriteReviewCommentArray[] = $favoriteReviewComment->favorited_id;
}
}
if (empty($ignoringArray)) {
$reviews = Review::with([
'product',
'user',
'favorites',
'reviewComments',
'reviewComments.favorites'
])
->where('created_at', '>=', Carbon::today()->subDays(7))
->paginate(20);
} elseif (! empty($ignoringArray)) {
$reviews = Review::whereNotIn('user_id', $ignoringArray)
->with('product', 'user', 'favorites', 'reviewComments.favorites')
->with([
'reviewComments' => function ($query) use ($ignoringArray) {
$query->whereNotIn('user_id', $ignoringArray);
}
])
->where('created_at', '>=', Carbon::today()->subDays(7))
->paginate(20);
}
return view('new-reviews.index', [
'reviews' => $reviews,
'favoriteReviewArray' => $favoriteReviewArray ?? null,
'favoriteReviewCommentArray' => $favoriteReviewCommentArray ?? null
]);
In the blade file:
@if(in_array($reviewComment->id, $favoriteReviewCommentArray ?? []))
@if(in_array($review->id, $favoriteReviewArray ?? []))
It's not pretty but it works.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | matiaslauriti |
