Simple Like System with Laravel 5

Simple Like System with Laravel 5


Sep 04 2015, 19:20 in Web Development

Update: A new and better way to build a Like System in Laravel is described in this article

Yo yo guys ! Today I'll be giving you a new tutorial on how to build a quite simple "Like" system onto your Laravel 5 application.

This "Like" system can be compared of course to the Facebook Like button, and you can name it as you like for your app, for example "+1" or "sweet" or "love" or whatever.

The goal is to get a count of the number of user that have "liked", or "+1'd" a specific entity.

Let's do it !

For the purpose of this tutorial, I will take the example of a blog, like this one. So we will have :

  1. a Post Model, with its own table "posts"
  2. and of course a User Model with its own "by default thanks to Laravel" table "users"

There are no direct links between these two models, because we are going to use a separate table, and thus a BelongsToMany Relationship, to store the number of likes.

First of all, create a new migration with the command php artisan make:migration create_likes_table --create=likes

Don't forget to quickly create a Like model with the command php artisan make:model Like. You don't need to add anything to the generated file.

Now go ahead and edit your new migration file. The up() method should look like this :

public function up()
{
    Schema::create('likes', function(Blueprint $table)
    {
        $table->increments('id');
        $table->integer('post_id');
        $table->integer('user_id');
        $table->softDeletes();
        $table->timestamps();
    });
}

The use of the softDelete column is really important, and I'll explain why in a minute.

Now let's set the relation methods into our models:

User.php

public function likes()
{
    return $this->belongsToMany('App\Post', 'likes', 'user_id', 'post_id');
}

And Post.php

public function likes()
{
    return $this->belongsToMany('App\User', 'likes');
}

Now that our logic is in place and ready to be used, we simply need to create the methods and the scripts that will add, delete and check user likes. There are several ways to go : build an API and use AJAX call, or use simple routes and links but your users will need to reload the page each time. In a User Experience point of view, the AJAX way is definitely the way to go.

I personally managed to only use two routes, and thus two methods, to do all I need.

Go ahead and add these to your routes file :

Route::get('post/{id}/islikedbyme', 'API\PostController@isLikedByMe');
Route::post('post/like', 'API\PostController@like');

And in your API/PostController.php file, add these two methods :

public function isLikedByMe($id)
{
    $post = Post::findOrFail($id)->first();
    if (Like::whereUserId(Auth::id())->wherePostId($post->id)->exists()){
        return 'true';
    }
    return 'false';
}

public function like(Post $post)
{
    $existing_like = Like::withTrashed()->wherePostId($post->id)->whereUserId(Auth::id())->first();

    if (is_null($existing_like)) {
        Like::create([
            'post_id' => $post->id,
            'user_id' => Auth::id()
        ]);
    } else {
        if (is_null($existing_like->deleted_at)) {
            $existing_like->delete();
        } else {
            $existing_like->restore();
        }
    }
}

Now you understand why it's important to use the Soft Delete logic. Indeed, if you want to notify the post's author when he got a new Like, well if the user Like / Unlike the same post ten times, you don't want to send 10 notifications to the author. Only one notification when a new like is inserted into the database.

Last step is to use your favorite Javascript framework to make get and post requests to the two routes. The first one only check if the Authenticated user like the post or not. And the post route, where you only need to pass the post's id as an input, will like or unlike the post.

There are tons of way to do this in JS, and I trust that you can make these simple ajax calls :) If you would like to see an example, just ask in the comments and I'll provide one based on AngularJS.

Enjoy your community interactions !


Share:
Like:

Disable AdBlock on this domain and offer me a cup of coffee :)