laravel rating system

Laravel Rating System

Today, I will give you an example of “How to create Rating System in Laravel”, So you can easily apply it with your laravel 5, laravel 6, laravel 7, and laravel 8 application.

First, what we’re doing here, This is the example :

post list laravel

review rating system in laravel

Easy Way to Implement Review Rating System in Laravel

Review rating is the most common module in every application, mostly you will see the review and rating system in e-commerce platforms where there is an option after every product to rate or review by the user to share his experience or feedback.

For example, to implement a review and rating system in the laravel application we create and store some posts in the database and then implement a review and rating platform after every post, where the user can select stars rating and write his comment.

Let’s get started.

Generating Migration

We create new migration files for the “posts” and “review_ratings” table, In your cmd terminal hit the given below command.

php artisan make:migration create_posts_table
php artisan make:migration create_review_ratings_table

Migration Structures

Post Table Migration

<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->longText('description');
            $table->string('author');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Review Rating Table Migration

<?php

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

class CreateReviewRatingsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('review_ratings', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('post_id');
            $table->string('name');
            $table->string('email');
            $table->string('phone');
            $table->longText('comments')->nullable();
            $table->integer('star_rating');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('review_ratings');
    }
}

Run Migration

php artisan migrate

Posts Table :-

post table migration

Review Ratings Table :-

rating review table migration

Create Models

php artisan make:model Post
php artisan make:model ReviewRating

app\Models\Post.php

<?php

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
   
    public function ReviewData()
    {
    return $this->hasMany('App\Models\ReviewRating','post_id');
    }
}

Note :- Create a hasMany Relationship

We create a hasMany relationship in Post Model, we store post table (primary id) as a foreign key (post_id) in review_ratings table, whenever users will submit their own review or rate on each post.
    public function ReviewData()
    {
    return $this->hasMany('App\Models\ReviewRating','post_id');
    }

app\Models\ReviewRating.php

<?php

namespace App\Models;

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

class ReviewRating extends Model
{
    use HasFactory;
}

Create a Controller

php artisan make:controller PostController

Define Web Routes

routes\web.php

<?php

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


/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

#Manage Post
Route::get('/post-create',[PostController::class, 'create'])->name('post.create');
Route::post('/post-store',[PostController::class, 'store'])->name('post.store');
Route::get('/post-list',[PostController::class, 'list'])->name('post.list');
Route::get('/post-view/{id}',[PostController::class, 'view'])->name('post.view');

#Manage Review
Route::post('/review-store',[PostController::class, 'reviewstore'])->name('review.store');

app\Http\Controllers\PostController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;
use App\Models\ReviewRating;
use Session;

class PostController extends Controller
{
    public function create()
    {
        return view('post.create');
    }

    public function store(Request $request){
        $post = new Post();
        $post->author = $request->author;
        $post->title  = $request->title;
        $post->description = $request->description;
        $post->save();
        return redirect()->route('post.list');

    }

    public function list()
    {
        $posts = Post::orderBy('id','desc')->get();
        return view('post.list',compact('posts'));
    }

    public function view($id){
        $post_detail = Post::with('ReviewData')->find($id);
        return view('post.view',compact('post_detail'));
    }

    public function reviewstore(Request $request){
        $review = new ReviewRating();
        $review->post_id = $request->post_id;
        $review->name    = $request->name;
        $review->email   = $request->email;
        $review->phone   = $request->phone;
        $review->comments= $request->comment;
        $review->star_rating = $request->rating;
        $review->save();
        return redirect()->back()->with('flash_msg_success','Your review has been submitted Successfully,');
    }
}

Create Blade Files

Now, we make a post folder in views and then create these 3 files given below-:

  • Create.blade.php
  • list.blade.php
  • view.blade.php

resources\views\post\create.blade.php

create post blade file
<!DOCTYPE html>
<html>
   <head>
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
      <style>
         a {
         color: #BE206B!important;
         }
         a.btn.btn-lg.btn-block,.btn-info {
         color: white !important;
         }
         .btn-secondary {
         background-color: #448BC6!important;
         color: #fff!important;
         }
         button.btn.btn.btn-secondary {
         width: 100%;
         }
         h3 {
         text-align: center;
         line-height: 200%;
         }
         .collpa
         .pt-0, .py-0 {
         padding-top: 0!important;
         }
         .rate {
         float: left;
         height: 46px;
         padding: 0 10px;
         }
         .rate:not(:checked) > input {
         position:absolute;
         display: none;
         }
         .rate:not(:checked) > label {
         float:right;
         width:1em;
         overflow:hidden;
         white-space:nowrap;
         cursor:pointer;
         font-size:30px;
         color:#ccc;
         }
         .rate:not(:checked) > label:before {
         content: '★ ';
         }
         .rate > input:checked ~ label {
         color: #ffc700;
         }
         .rate:not(:checked) > label:hover,
         .rate:not(:checked) > label:hover ~ label {
         color: #deb217;
         }
         .rate > input:checked + label:hover,
         .rate > input:checked + label:hover ~ label,
         .rate > input:checked ~ label:hover,
         .rate > input:checked ~ label:hover ~ label,
         .rate > label:hover ~ input:checked ~ label {
         color: #c59b08;
         }
         .rating-container .form-control:hover, .rating-container .form-control:focus{
         background: #fff;
         border: 1px solid #ced4da;
         }
         .rating-container textarea:focus, .rating-container input:focus {
         color: #000;
         }
         /* new page css */
      </style>
   </head>
   <main>
      <div class="container">
      <div class="row justify-content-center">
         <div class="col-lg-6">
            <div class="main">
               <h3><a>Laravel 8 Review Rating System.</a></h3>
               <form role="form" action="{{route('post.store')}}" method="post">
                  @csrf
                  <div class="form-group">
                     <label for="title">Post Title<span class="text-danger">*</span></label>
                     <input type="text" name="title" class="form-control" required>
                  </div>
                  <div class="form-group">
                     <label for="author">Post Author<span class="text-danger">*</span></label>
                     <input type="text" name="author" class="form-control" required>
                  </div>
                  <div class="form-group">
                     <label for="description">Post Description<span class="text-danger">*</span></label>
                     <input type="text" name="description" class="form-control" required>
                  </div>
                  <div class="form-group">
                     <button type="submit" class="btn btn btn-secondary">save</button>
               </form>
               </div>
            </div>
         </div>
      </div>
   </main>
   </body>
</html>

resources\views\post\list.blade.php

list post blade file
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
  box-sizing: border-box;
}

/* Add a gray background color with some padding */
body {
  font-family: Arial;
  padding: 20px;
  background: #f1f1f1;
}

/* Header/Blog Title */
.header {
  padding: 30px;
  font-size: 40px;
  text-align: center;
  background: white;
}

/* Create two unequal columns that floats next to each other */
/* Left column */
.leftcolumn {   
  float: left;
  width: 75%;
}

/* Right column */
.rightcolumn {
  float: left;
  width: 25%;
  padding-left: 20px;
}

/* Fake image */
.fakeimg {
  background-color: #aaa;
  width: 100%;
  padding: 20px;
}

/* Add a card effect for articles */
.card {
   background-color: white;
   padding: 20px;
   margin-top: 20px;
}

/* Clear floats after the columns */
.row:after {
  content: "";
  display: table;
  clear: both;
}

</style>
</head>
<body>

<div class="header">
  <h2>Laravel 8 Review Rating System | 8bityard.com.</h2>
</div>

<div class="row">
  <div class="leftcolumn">

   @foreach($posts as $post)
    <div class="card">
      <h2 style="color:#0071a1;">{{ $post->title }}</h2>
      <h5 style="color:#e91e63;">Published at : {{$post->created_at->format('jS \\of F Y') }}</h5>
      
      
      <p>{{ $post->description }}</p>
      <p><b><a href="{{route('post.view',$post->id)}}">Read Article</a></b></p>

    </div>

   @endforeach
  </div>
  <div class="rightcolumn">
    <div class="card">
      <h2>About Me</h2>
      <img class="fakeimg" style="height:100px;" src="https://8bityard.com/ezoimgfmt/mllibnjakigh.i.optimole.com/e4PqOHU-NUmggukx/w:110/h:48/q:auto/https://8bityard.com/wp-content/uploads/2020/05/cropped-cropped-LogoMakr_48yknb-2.png?ezimgfmt=rs:110x48/rscb1/ng:webp/ngcb1">
      <p>Laravel | WordPress | JQuery.</p>
    </div>
</div>
</div>
</div>
</body>
</html>

Recommended Article :- Encrypt and Decrypt Id in Laravel.

resources\views\post\view.blade.php

view post blade file
<!DOCTYPE html>
<html>
   <head>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
      <style>
         * {
         box-sizing: border-box;
         }
         /* Add a gray background color with some padding */
         body {
         font-family: Arial;
         padding: 20px;
         background: #f1f1f1;
         }
         /* Header/Blog Title */
         .header {
         padding: 30px;
         font-size: 40px;
         text-align: center;
         background: white;
         }
         /* Create two unequal columns that floats next to each other */
         /* Left column */
         .leftcolumn {   
         float: left;
         width: 75%;
         }
         /* Right column */
         .rightcolumn {
         float: left;
         width: 25%;
         padding-left: 20px;
         }
         /* Fake image */
         .fakeimg {
         background-color: #aaa;
         width: 100%;
         padding: 20px;
         }
         /* Add a card effect for articles */
         .card {
         background-color: white;
         padding: 20px;
         margin-top: 20px;
         }
         /* Clear floats after the columns */
         .row:after {
         content: "";
         display: table;
         clear: both;
         }
         .avatar {
         vertical-align: middle;
         width: 50px;
         height: 50px;
         border-radius: 50%;
         }
         .rate {
         float: left;
         height: 46px;
         padding: 0 10px;
         }
         .rate:not(:checked) > input {
         position:absolute;
         display: none;
         }
         .rate:not(:checked) > label {
         float:right;
         width:1em;
         overflow:hidden;
         white-space:nowrap;
         cursor:pointer;
         font-size:30px;
         color:#ccc;
         }
         .rate:not(:checked) > label:before {
         content: '★ ';
         }
         .rate > input:checked ~ label {
         color: #ffc700;
         }
         .rate:not(:checked) > label:hover,
         .rate:not(:checked) > label:hover ~ label {
         color: #deb217;
         }
         .rate > input:checked + label:hover,
         .rate > input:checked + label:hover ~ label,
         .rate > input:checked ~ label:hover,
         .rate > input:checked ~ label:hover ~ label,
         .rate > label:hover ~ input:checked ~ label {
         color: #c59b08;
         }
         .rating-container .form-control:hover, .rating-container .form-control:focus{
         background: #fff;
         border: 1px solid #ced4da;
         }
         .rating-container textarea:focus, .rating-container input:focus {
         color: #000;
         }
         /* End */
      </style>
   </head>
   <body>
      <div class="header">
         <h2>Laravel 8 Review Rating System | 8bityard.com.</h2>
      </div>
      <div class="row">
         <div class="leftcolumn">
            <div class="card">
               <h2 style="color:#0071a1;">{{ $post_detail->title }}</h2>
               <p style="color:#e91e63;">Published at : {{$post_detail->created_at->format('jS \\of F Y') }}</p>
               <p>{{ $post_detail->description }}</p>
               <hr>
               <!-- Display review section start -->
               <div data-spy="scroll" data-target="#navbar-example2" data-offset="0">
                  <div>
                     <div class="row mt-5">
                        <h4>Comment Section :</h4>
                        <div class="col-sm-12 mt-5">
                           @foreach($post_detail->ReviewData as $review)
                           <div class=" review-content">
                              <img src="https://www.w3schools.com/howto/img_avatar.png" class="avatar ">
                              <span class="font-weight-bold ml-2">{{$review->name}}</span>
                              <p class="mt-1">
                                 @for($i=1; $i<=$review->star_rating; $i++) 
                                 <span><i class="fa fa-star text-warning"></i></span>
                                 @endfor
                                 <span class="font ml-2">{{$review->email}}</span>
                              </p>
                              <p class="description ">
                                 {{$review->comments}}
                              </p>
                           </div>
                           <hr>
                           @endforeach
                        </div>
                     </div>
                  </div>
               </div>
               <!-- Review store Section -->
               <div class="container">
                  <div class="row">
                     <div class="col-sm-10 mt-4 ">
                        <form class="py-2 px-4" action="{{route('review.store')}}" style="box-shadow: 0 0 10px 0 #ddd;" method="POST" autocomplete="off">
                           @csrf
                           <input type="hidden" name="post_id" value="{{$post_detail->id}}">
                           <div class="row justify-content-end mb-1">
                              <div class="col-sm-8 float-right">
                                 @if(Session::has('flash_msg_success'))
                                 <div class="alert alert-success alert-dismissible p-2">
                                    <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                                    <strong>Success!</strong> {!! session('flash_msg_success')!!}.
                                 </div>
                                 @endif
                              </div>
                           </div>
                           <p class="font-weight-bold ">Review</p>
                           <div class="form-group row">
                              <div class=" col-sm-6">
                                 <input class="form-control" type="text" name="name" placeholder="Name" maxlength="40" required/>
                              </div>
                              <div class="col-sm-6">
                                 <input class="form-control" type="email" name="email" placeholder="Email" maxlength="80" required/>
                              </div>
                           </div>
                           <div class="form-group row">
                              <div class="col-sm-6">
                                 <input class="form-control" type="text" name="phone" placeholder="Phone" maxlength="40" required/>
                              </div>
                              <div class="col-sm-6">
                                 <div class="rate">
                                    <input type="radio" id="star5" class="rate" name="rating" value="5"/>
                                    <label for="star5" title="text">5 stars</label>
                                    <input type="radio" checked id="star4" class="rate" name="rating" value="4"/>
                                    <label for="star4" title="text">4 stars</label>
                                    <input type="radio" id="star3" class="rate" name="rating" value="3"/>
                                    <label for="star3" title="text">3 stars</label>
                                    <input type="radio" id="star2" class="rate" name="rating" value="2">
                                    <label for="star2" title="text">2 stars</label>
                                    <input type="radio" id="star1" class="rate" name="rating" value="1"/>
                                    <label for="star1" title="text">1 star</label>
                                 </div>
                              </div>
                           </div>
                           <div class="form-group row mt-4">
                              <div class="col-sm-12 ">
                                 <textarea class="form-control" name="comment" rows="6 " placeholder="Comment" maxlength="200"></textarea>
                              </div>
                           </div>
                           <div class="mt-3 ">
                              <button class="btn btn-sm py-2 px-3 btn-info">Submit
                              </button>
                           </div>
                        </form>
                     </div>
                  </div>
               </div>
            </div>
         </div>
         <div class="rightcolumn">
            <div class="card">
               <h2>About Me</h2>
               <img class="fakeimg" style="height:100px;" src="https://8bityard.com/ezoimgfmt/mllibnjakigh.i.optimole.com/e4PqOHU-NUmggukx/w:110/h:48/q:auto/https://8bityard.com/wp-content/uploads/2020/05/cropped-cropped-LogoMakr_48yknb-2.png?ezimgfmt=rs:110x48/rscb1/ng:webp/ngcb1">
               <p>Laravel | WordPress | JQuery.</p>
            </div>
         </div>
      </div>
   </body>
</html>

Note : We store post-primary ID as hidden in review_ratings table as a post_id (foreign_key) to get all related reviews and comments.

<input type="hidden" name="post_id" value="{{$post_detail->id}}">

Run Application :

127.0.0.1:8000/post-list
all post list

review and rating system in laravel

create star rating system in laravel

user comment with star rating in laravel

In this article, we successfully integrated “Laravel Review and Rating System Example”, I hope this article will help you with your Laravel application Project.

Read also: How to send contact form data in mail Laravel?

Hi, My name is Gaurav Pandey. I'm a Laravel developer, owner of 8Bityard. I live in Uttarakhand - India and I love to write tutorials and tips that can help other developers. I am a big fan of PHP, Javascript, JQuery, Laravel, WordPress. connect@8bityard.com