Skip to content
All posts
Laravel

Like/Dislike Mechanism in Laravel

May 19, 2022·Read on Medium·
Photo by Daniela Holzer on Unsplash

Like-dislike function are widely found in social media, blogs, mobile apps which represent how the users like the content or not. The purpose of this like-dislike function is where we want to enhances the User Experience and gains the user’s feedback for their uploaded content.

In this articles, i will show you how to implement this function without using any packages and it’s pretty simple. Here’s the steps

  1. Create Like Table and Model
  2. Create 2 Traits :- HasLikes and HasLikeable
  3. Implement Traits to related models
  4. How to use

Lets get started

I assumed that you already have installed Laravel in your environment. So will straight to create a migration to add new table for Like.

Create Like Table and Model

Run make model command including migration file :-

php artisan make:model Like -m

Now, go your migrations folder and open the latest migration file. The name will like this XXXX_XX_XX_XXXXXX_create_likes_table.php.

The situation is where Like or Dislike must have :-

  1. Who pressed like-dislike button.
  2. Which content that user referring.
  3. Which button that user clicked on (like or dislike).

Adjust the migration file like below :-

Schema::create('followers', function (Blueprint $table) {
$table->id();

$table->morphs('userable');

$table->morphs('likeable');

$table->boolean('is_liked')->default(true)->index();

$table->timestamps();
});

The purpose we use morph relationship is because we want this table can be use by another content model and the user can be as another user model as well. We add a boolean column called is_liked because we just focus on like or dislike which represent true or false. You can changed the column into integer if you have many like types like emotions. And of course, we might want to store when the data stored in database using timestamps.

Open the Like Model and add relationship method for user and likeable content

class Like extends Model
{
use HasFactory; protected $fillable = ['is_liked']; public function likeable()
{
return $this->morphTo();
}


public function userable()
{
return $this->morphTo();
}
}

Create Traits — HasLikes and HasLikeable

Now, we need to create two traits

  1. HasLikes — referring for the content model usage
  2. HasLikeable — referring for the who like the content (user)

Before that we need to create interface class called Likeable. Why? because we need to allows unrelated classes to implement the same set of methods for the content model.

Create Likeable class

interface Likeable
{
public function likes(): MorphMany;
public function dislikes(): MorphMany;
}

So now, we need to create HasLikes class and add only morph relationship

trait HasLikes
{
public function likes(): MorphMany
{
return $this->morphMany(Like::class, 'likeable')->where('is_like', true);
} public function dislikes(): MorphMany
{
return $this->morphMany(Like::class, 'likeable')->where('is_like', false);
}
}

Create HasLikeable and follow the code below:-

trait HasLikeable
{
public function like(Likeable $likeable, $state = true)
{
if ($like = $likeable->likes()->whereMorphedTo('userable', $this)->first()) {
$like->update([
'is_liked' => $state
]);

return;
}

app(Like::class)
->userable()->associate($this)
->likeable()->associate($likeable)
->fill([
'is_liked' => $state
])
->save();
}

public function unlike(Likeable $likeable)
{
$likeable->likes()
->whereMorphedTo('userable', $this)
->delete();
}

public function dislike(Likeable $likeable)
{
$this->like($likeable, false);
}
}

Here we have 3 methods :- like, unlike and dislike. The solution is straight forward. The logic for the like method is where if not exist, then we create a new row associate with the related user and content model, else just update the column. For the dislike, we just call the like method with false argument. For the unlike, i would prefer we just delete the row.

Implement to the models

Now, we need to adjust the related models. For example, i assumed, we have User class and Post class. User can like Post and Post is likeable by User.

Open the User model class and add trait HasLikeable

class User extends Authenticatable
{

use HasLikeable;
...
...

}

Open Post model class. Add trait HasLikes and interface Likeable

class Post implement Likeable 
{
use HasLikes;
...
...
}

If you have another users class which can have like features, simple make the as the user class, for example :-

class AppUser extends Authenticatable
{

use HasLikeable;
...
...

}

Same goes to the content model. You can implement the same the Post model.

How to use?

The usage is simple straight forward

auth()->user()->like(YOUR_LIKEABLE_MODEL);

Just pass the model object into the method and the function will do all the rest. Here is some example: -

public function like(Request $request, Blog $blog)
{
auth()->user()->like($blog);

return response()->json(['message' => 'Success']);
}

public function unlike(Request $request, Blog $blog)
{
auth()->user()->unlike($blog);

return response()->json(['message' => 'Success']);
} public function dislike(Request $request, Blog $blog)
{
auth()->user()->dislike($blog);

return response()->json(['message' => 'Success']);
}

If you want to count how many likes, dislikes the model has, simply

Blog::withCount(['likes', 'dislikes'])->find(1);

If you want to get all your likes and dislikes from current users

Like::query()->whereMorphedTo('userable', auth()->user())->get();

Now you’re good to go. 😁

References

Found this helpful?

If this article saved you time or solved a problem, consider supporting — it helps keep the writing going.

Originally published on Medium.

View on Medium
Like/Dislike Mechanism in Laravel — Hafiq Iqmal — Hafiq Iqmal