Today we are going to build a Like and Dislike system. To implement this application, we use php framework Laravel and Progressive JavaScript Framework Vue.js.

Prerequisites

  • Laravel
  • To Continue with this tutorial, you should have installed Laravel 8 in your pc. If you are still not installed Laravel in your machine you can configure it from here.
  • Vue.jS
  • You can refer the official Vue.js documentation from here.

    Setting up the Project

    First you need to create a new laravel project by running below command in your terminal
    1
    composer create-project laravel/laravel laravel-vue-like-dislike-system --prefer-dist

    Then navigate to your project directory by using below command in your terminal

    1
    cd laravel-vue-like-dislike-system

    Setting up Database

    To setup up Database for our project, open the application using your favourite text editor and and then navigate to .env file in it and then change below section acording to your Database settings:

    1
    2
    3
    4
    5
    6
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=laravel-vue-like-dislike
    DB_USERNAME=root
    DB_PASSWORD=

    Set Up Model and Run Migration

    Now we need to need to generate Model & Migration file which related to our Blog section:
    1
    php artisan make:model Blog -m

    After that you need to place below code in your database/migrations/create_blogs_table.php:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?php

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    class CreateBlogsTable extends Migration
    {
    public function up()
    {
    Schema::create('blogs', function (Blueprint $table) {
    $table->id();
    $table->string('post_title');
    $table->string('post_slug');
    $table->string('description');
    $table->unsignedBigInteger('user_id');
    $table->unsignedBigInteger('like')->default(0);
    $table->unsignedBigInteger('dislike')->default(0);
    $table->timestamps();
    });
    }

    public function down()
    {
    Schema::dropIfExists('blogs');
    }
    }

    Now pllace the below code in app/Models/Blog.php:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php

    namespace App\Models;

    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;

    class Blog extends Model
    {
    use HasFactory;
    protected $fillable = [
    'post_title',
    'description'
    ];

    public function getRouteKeyName()
    {
    return 'post_slug';
    }
    }

    Afterwards, we need to do database migration:

    1
    php artisan migrate

    Generate fake data

    For testing our application wee need to add some fake data. To do it add below code to your BlogSeeder.php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php

    namespace Database\Seeders;

    use Illuminate\Database\Seeder;

    class BlogSeeder extends Seeder
    {
    public function run(){

    Blog::create([
    'post_title' => $this->faker->unique()->sentence,
    'description' => $this->faker->paragraph,
    'post_slug' => $this->faker->unique()->sentence,
    'user_id' => 1,
    'created_at' => \Carbon\Carbon::now(),
    'updated_at' => \Carbon\Carbon::now(),
    ]);
    }
    }

    Then add below code for your DatabaseSeeder.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?php

    namespace Database\Seeders;

    use Illuminate\Database\Seeder;
    use App\Models\Blog;

    class DatabaseSeeder extends Seeder
    {
    public function run()
    {
    \App\Models\Blog::factory(10)->create();
    }

    }

    After that run below coomand to run seed:

    1
    php artisan db:seed

    Install Vue UI and NPM Dependencies

    To install Vue in our application in our Laravel project, run below command:
    1
    composer require laravel/ui

    Then,

    1
    php artisan ui vue
    1
    npm install

    Create Blog Controller

    In this stage we are going to make our BlogController which holds our all logic related to blog section like fetch all blogs, fetch single blog, like and dislike function and more. To generate our controller:
    1
    php artisan make:controller BlogController

    Then paste below command in it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;
    use Facades\App\Repository\Blogs;
    use App\Models\Blog;

    class BlogController extends Controller
    {
    public function index()
    {
    $blogs = Blog::latest()->get();
    return view('blog', ['blogs' => $blogs ]);
    }

    public function blogDetail(Blog $post_slug)
    {
    return view('blog-details', ['blog' => $post_slug ]);
    }

    public function fetchLike(Request $request)
    {
    $blog = Blog::find($request->blog);
    return response()->json([
    'blog' => $blog,
    ]);
    }

    public function handleLike(Request $request)
    {
    $blog = Blog::find($request->blog);
    $value = $blog->like;
    $blog->like = $value+1;
    $blog->save();
    }

    public function fetchDislike(Request $request)
    {
    $blog = Blog::find($request->blog);
    return response()->json([
    'blog' => $blog,
    ]);
    }

    public function handleDislike(Request $request)
    {
    $blog = Blog::find($request->blog);
    $value = $blog->dislike;
    $blog->dislike = $value+1;
    $blog->save();
    }
    }

    Create routes

    Now we need to define our routes for handling the like and dislike functions and show the views. Open routes/web.php and paste this code in it:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php

    use Illuminate\Support\Facades\Route;
    use App\Http\Controllers\BlogController;

    Route::get('/', [BlogController::class, 'index']);
    Route::get('/{post_slug?}', [BlogController::class, 'blogDetail'])->name('blog');

    Route::post('/like', [BlogController::class, 'fetchLike']);
    Route::post('/like/{id}', [BlogController::class, 'handleLike']);

    Route::post('/dislike', [BlogController::class, 'fetchDislike']);
    Route::post('/dislike/{id}', [BlogController::class, 'handleDislike']);

    Create Vue Components

    For this application we nned two Vue components. Head over to resources/assets/js/components directory, create two files, name them LikeComponent.vue and DislikeComponent.vue and add below command in LikeComponent.vue:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    <template>
    <div class="container">
    <div id="success" class="mb-3"></div>

    <a style="cursor: pointer" @click.prevent="likeBlog">
    <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>
    ({{ alllikes }})
    </a>
    </div>
    </template>

    <script>
    export default {
    props: ['blog'],
    data() {
    return {
    alllikes: '',
    }
    },
    methods: {
    likeBlog() {
    axios.post('/like/' + this.blog, {
    blog: this.blog
    })
    .then(res => {
    this.renderLike()
    $('#success').html(res.data.message)
    })
    .catch()
    },
    renderLike() {
    axios.post('/like', {
    blog: this.blog
    })
    .then(res => {
    console.log(res.data.blog.like)
    this.alllikes = res.data.blog.like
    })
    }
    },
    mounted() {
    this.renderLike()
    }
    }

    </script>

    Then, add below code in DislikeComponent.vue:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <template>
    <div class="container">
    <div id="success" class="mb-3"></div>

    <a style="cursor: pointer" @click.prevent="dislikeBlog">
    <i class="fa fa-thumbs-o-down" aria-hidden="true"></i>
    ({{ allDislike }})
    </a>
    </div>
    </template>

    <script>
    export default {
    props:['blog'],
    data(){
    return {
    allDislike:'',
    }
    },
    methods:{
    dislikeBlog(){
    axios.post('/dislike/'+this.blog, {blog: this.blog})
    .then(res =>{
    this.renderDislike()
    $('#success').html(res.data.message)
    })
    .catch()
    },
    renderDislike(){
    axios.post('/dislike', {blog:this.blog})
    .then(res =>{
    console.log(res.data.blog.dislike)
    this.allDislike = res.data.blog.dislike
    })
    }
    },
    mounted() {
    this.renderDislike()
    }
    }
    </script>

    In your resources/assets/js/app.js insert below code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    require('./bootstrap');

    window.Vue = require('vue').default;

    Vue.component('like-component', require('./components/LikeComponent.vue').default);
    Vue.component('dislike-component', require('./components/DislikeComponent.vue').default);

    const app = new Vue({
    el: '#app',
    });

    Setting Up Vue Component in Blade View

    Create a file called blog.blade.php in resources/views directory and add below code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @extends('layout.app')

    @section('content')

    <section class="tm-section">
    <div class="container-fluid">
    <div class="row">
    @foreach ($blogs as $data)
    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-3 col-xl-3">
    <div class="tm-content-box">
    <img src="img/tm-img-310x180-1.jpg" alt="Image" class="tm-margin-b-20 img-fluid">
    <h4 class="tm-margin-b-20 tm-gold-text">{{ $data->post_title }}</h4>
    <p class="tm-margin-b-20"></p>
    <a href="{{ route('blog', $data->post_slug) }}" class="tm-btn text-uppercase">Detail</a>
    </div>
    </div>
    @endforeach
    </div>
    </div>
    </section>

    @endsection

    Then create a file called blog-details.blade.php in resources/views directory and add below code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    @extends('layout.app')


    @section('content')

    <section class="tm-section">
    <div class="container-fluid">
    <div class="row">
    <div class="col-xs-12 col-sm-12 col-md-8 col-lg-9 col-xl-9">
    <div class="tm-blog-post">
    <h3 class="tm-gold-text">{{ $blog->post_title }}</h3>
    <img src="{{ asset('img/tm-img-1010x336-1.jpg') }}" alt="Image" class="img-fluid tm-img-post">

    <p>{{ $blog->description }}</p>
    <div class="row">
    <div class="col">
    <like-component :blog="{{ $blog->id }}"></like-component>
    </div>
    <div class="col">
    <dislike-component :blog="{{ $blog->id }}"></dislike-component>
    </div>
    </div>
    </div>
    </div>
    </div>
    </div>
    </section>

    @endsection

    Then you need to create folder called layout in resources/views and then create a file called app.blade.php and pastle below code in it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>Laravel Vue JS Like Dislike Demo</title>


    <link rel="stylesheet" href="{{ asset('css/bootstrap.min.css') }}">
    <link rel="stylesheet" href="{{ asset('css/templatemo-style.css') }}">

    <script src="{{ asset('js/app.js') }}" defer></script>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.0/css/font-awesome.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400">


    </head>
    <body>
    <div id="app">

    <main class="py-4">
    @yield('content')
    </main>

    </div>

    <script src="{{ asset('js/jquery-1.11.3.min.js') }}"></script>
    <script src="{{ asset('https://www.atlasestateagents.co.uk/javascript/tether.min.js') }}"></script>
    <script src="{{ asset('js/bootstrap.min.js') }}"></script>

    </body>
    </html>

    Note:

    you can obtain all the required js and css file from the public folder in my Github repo.

    Run Application

    To run our appliction run below commands in two different terminals:
    1
    npm run watch
    1
    php artisan serve

    Then navigate to http://127.0.0.1:8000

    Conclusion

    In this tutorial, we implemented a simple Like and Dislike system using Laravel and Vue.js. If you have any issue regarding this tutorial, mention your issue in the comment section or reach me through my E-mail. You can obtain complete source code for this tutorial from this GitHub repository.