Laravel 8 E-Commerce - User Review & Rating on Product

In this video, we will learn about user reviews and ratings on products.

Let's explore how users can add reviews and ratings to products.

First, we need to create a model and migration for reviews.

Switch to the command prompt and run the following command:


php artisan make:model Review –m

Now, switch to the project and open the create_reviews_table migration file. Add the following code:


<?php

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

class CreateReviewsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->integer('rating');
$table->text('comment');
$table->bigInteger('order_item_id')->unsigned();
$table->timestamps();
$table->foreign('order_item_id')->references('id')->on('order_items')->onDelete('cascade');
});
}

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

Next, we need to add a column to the OrderItems table.

Switch to the command prompt and create a migration for adding a new column to the orderitems table:


php artisan make:migration add_rstatus_to_order_items_table --table= order_items

Now, switch to the project and open the new migration file. Add the following code:


<?php

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

class AddRstatusToOrderItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('order_items', function (Blueprint $table) {
$table->boolean('rstatus')->default(false);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('order_items', function (Blueprint $table) {
$table->dropColumn('rstatus');
});
}
}

Now, let's migrate the migration.

Go to the command prompt and run the following command:


php artisan migrate

Run the application:


php artisan serve

Switch to the project and open the user-order-details.blade.php component view file. Modify the code as follows in the ordered items panel:


<div class="wrap-iten-in-cart">
<h3 class="box-title">Products Name</h3>
<ul class="products-cart">
@foreach ($order->orderItems as $item)
<li class="pr-cart-item">
<div class="product-image">
<figure><img src="{{ asset('assets/images/products') }}/{{$item->product->image}}" alt="{{$item->product->name}}"></figure>
</div>
<div class="product-name">
<a class="link-to-product" href="{{route('product.details',['slug'=>$item->product->slug])}}">{{$item->product->name}}</a>
</div>
<div class="price-field produtc-price"><p class="price">${{$item->price}}</p></div>
<div class="quantity">
<h5>{{$item->quantity}}</h5>
</div>
<div class="price-field sub-total"><p class="price">${{$item->price * $item->quantity}}</p></div>
@if($order->status == 'delivered' && $item->rstatus == false)
<div class="price-field sub-total"><p class="price"><a href="{{route('user.review',['order_item_id'=>$item->id])}}">Write Review</a></p></div>
@endif
</li>
@endforeach
</ul>
</div>

Create a new Livewire component:

Switch to the command prompt and run the following command:


php artisan make:livewire user/UserReviewComponent

Run the application again:


php artisan serve

Switch to the project and create a route for this new component.

Go to the web.php file and inside the user middleware route group, create a new route:


Route::get('/user/review/{order_item_id}',UserReviewComponent::class)->name('user.review');

Open the UserReviewComponent.php class file and write the following code:


<?php

namespace App\Http\Livewire\User;

use App\Models\OrderItem;
use App\Models\Review;
use Livewire\Component;

class UserReviewComponent extends Component
{
public $order_item_id;
public $rating;
public $comment;

public function mount($order_item_id)
{
$this->order_item_id = $order_item_id;
}

public function updated($fields)
{
$this->validateOnly($fields,[
'rating' => 'required',
'comment' => 'required'
]);
}

public function addReview()
{
$this->validate([
'rating' => 'required',
'comment' => 'required'
]);
$review = new Review();
$review->rating = $this->rating;
$review->comment = $this->comment;
$review->order_item_id= $this->order_item_id;
$review->save();

$orderItem = OrderItem::find($this->order_item_id);
$orderItem->rstatus = true;
$orderItem->save();
session()->flash('message','Your review has been added successfully!');
}

public function render()
{
$orderItem = OrderItem::find($this->order_item_id);
return view('livewire.user.user-review-component',['orderItem'=>$orderItem])->layout('layouts.base');
}
}

Open the user-review-component.blade.php view file and write the following code:


<div>
<div class="container" style="padding: 30px 0;">
<div class="row">
<div class="col-md-12">
<div id="review_form_wrapper">
<div id="comments">
<h2 class="woocommerce-Reviews-title">Add review for</h2>
<ol class="commentlist">
<li class="comment byuser comment-author-admin bypostauthor even thread-even depth-1" id="li-comment-20">
<div id="comment-20" class="comment_container">
<img alt="" src="{{ asset('assets/images/products') }}/{{$orderItem->product->image}}" height="80" width="80">
<div class="comment-text">
<p class="meta">
<strong class="woocommerce-review__author">{{$orderItem->product->name}}</strong>
</p>
</div>
</div>
</li>
</ol>
</div><!-- #comments -->
<div id="review_form">
@if(Session::has('message'))
<p class="alert alert-success" role="alert">{{Session::get('message')}}</p>
@endif
<div id="respond" class="comment-respond">
<form wire:submit.prevent="addReview" id="commentform" class="comment-form">
<div class="comment-form-rating">
<span>Your rating</span>
<p class="stars">

<label for="rated-1"></label>
<input type="radio" id="rated-1" name="rating" value="1" wire:model="rating">
<label for="rated-2"></label>
<input type="radio" id="rated-2" name="rating" value="2" wire:model="rating">
<label for="rated-3"></label>
<input type="radio" id="rated-3" name="rating" value="3" wire:model="rating">
<label for="rated-4"></label>
<input type="radio" id="rated-4" name="rating" value="4" wire:model="rating">
<label for="rated-5"></label>
<input type="radio" id="rated-5" name="rating" value="5" checked="checked" wire:model="rating">
@error('rating') <span class="text-danger">{{$message}}</span> @enderror
</p>
</div>
<p class="comment-form-comment">
<label for="comment">Your review <span class="required">*</span>
</label>
<textarea id="comment" name="comment" cols="45" rows="8" wire:model="comment"></textarea>
@error('comment') <span class="text-danger">{{$message}}</span> @enderror
</p>
<p class="form-submit">
<input name="submit" type="submit" id="submit" class="submit" value="Submit">
</p>
</form>

</div><!-- .comment-respond-->
</div><!-- #review_form -->
</div><!-- #review_form_wrapper -->
</div>
</div>
</div>
</div>

Now, let's test it out.

Switch to your browser and refresh the page.

Click on the "Details" link, and you'll see that the "Write Review" link is not visible because the order has been canceled.

Let's check another order.

Click on the order that has a status of "Delivered".

You should see the "Write Review" link.

From here, you can set the rating by clicking on the star icon.

In the textarea, you can add a review or comment.

Write a review and click "Submit".

The review has been added, and the "Write Review" link is removed.

In the same way, you can write reviews for other products.

And that's how you can create a user review and rating system on products.