DEV Community

Discussion on: How to implement a simple like system with Laravel

Collapse
 
bdelespierre profile image
Benjamin Delespierre • Edited

I have just tried

$posts = Post::latest()->with('likes')->take(5)->get();
Enter fullscreen mode Exit fullscreen mode

Using the demo project and Laravel Debug bar.

From 8 queries (with the N+1) problem you mention, I now have only 4 👍

See before and after

Hint: be sure to place the ->with('...') part BEFORE ->get() or ->all().

Collapse
 
stleroux profile image
stleroux

Actually, I was using the code in the index page and doing a @can ('like') and @can ('unlike') which was querying the DB twice per record. I changed the @can ('unlike') for @else and now the duplicate queries are gone.
Thanks

Thread Thread
 
bdelespierre profile image
Benjamin Delespierre • Edited

Yes, that's because the gates in AuthServiceProvider are using User::hasLike :

    public function hasLiked(Likeable $likeable): bool
    {
        if (! $likeable->exists) {
            return false;
        }

        return $likeable->likes()
            ->whereHas('user', fn($q) =>  $q->whereId($this->id))
            ->exists();
    }
Enter fullscreen mode Exit fullscreen mode

You may change it to use a cache, like this (actual working solution) :

    public function hasLiked(Likeable $likeable): bool
    {
        if (! $likeable->exists) {
            return false;
        }

        return $this->likes->contains(
            fn($like) => $like->likeable_type == get_class($likeable) && $like->likeable_id == $likeable->id
        );
    }
Enter fullscreen mode Exit fullscreen mode

It should minimize the number of queries. It's ugly but it works!

Result before with 15 queries (one per @can('like')) and after only 6!