'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