Loading...
+880 1736 699819 Mon - Sat: 9:00 AM - 8:00 PM
Follow us:
Home Blog Article
Blog

Product Review & Rating Laravel API

Product Review & Rating Laravel API

 Product Review & Rating Laravel API 

1️⃣ Database Migration

product_reviews table

php artisan make:migration create_product_reviews_table

Schema::create('product_reviews', function (Blueprint $table) { $table->id(); $table->foreignId('product_id')->constrained()->cascadeOnDelete(); $table->foreignId('user_id')->constrained()->cascadeOnDelete(); $table->tinyInteger('rating')->unsigned(); // 1–5 $table->text('review')->nullable(); $table->timestamps(); $table->unique(['product_id', 'user_id']); // prevent duplicate });

2️⃣ Model

ProductReview.php

class ProductReview extends Model
{
    protected $fillable = [
        'product_id',
        'user_id',
        'rating',
        'review',
    ];

    protected $casts = [
        'rating' => 'integer',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function product()
    {
        return $this->belongsTo(Product::class);
    }
}

3️⃣ Product Model Relation

public function reviews()
{
    return $this->hasMany(ProductReview::class);
}

public function averageRating()
{
    return $this->reviews()->avg('rating');
}

4️⃣ API Routes

Route::middleware('auth:sanctum')->group(function () {
    Route::post('/products/{product}/reviews', [ProductReviewController::class, 'store']);
    Route::put('/products/{product}/reviews', [ProductReviewController::class, 'update']);
    Route::delete('/products/{product}/reviews', [ProductReviewController::class, 'destroy']);
});

Route::get('/products/{product}/reviews', [ProductReviewController::class, 'index']);

5️⃣ Controller

ProductReviewController.php

class ProductReviewController extends Controller
{
    // 📌 List reviews
    public function index(Product $product)
    {
        $reviews = ProductReview::with('user:id,name')
            ->where('product_id', $product->id)
            ->latest()
            ->get();

        return response()->json([
            'average_rating' => round($product->reviews()->avg('rating'), 2),
            'total_reviews'  => $reviews->count(),
            'reviews'        => $reviews
        ]);
    }

    // 📌 Store review
    public function store(Request $request, Product $product)
    {
        $request->validate([
            'rating' => 'required|integer|min:1|max:5',
            'review' => 'nullable|string'
        ]);

        $review = ProductReview::updateOrCreate(
            [
                'product_id' => $product->id,
                'user_id' => Auth::id()
            ],
            [
                'rating' => $request->rating,
                'review' => $request->review
            ]
        );

        return response()->json([
            'status'  => 'success',
            'message' => 'Review submitted successfully',
            'data'    => $review
        ], 201);
    }

    // 📌 Update review
    public function update(Request $request, Product $product)
    {
        $request->validate([
            'rating' => 'required|integer|min:1|max:5',
            'review' => 'nullable|string'
        ]);

        $review = ProductReview::where('product_id', $product->id)
            ->where('user_id', Auth::id())
            ->firstOrFail();

        $review->update($request->only('rating', 'review'));

        return response()->json([
            'status' => 'success',
            'message' => 'Review updated',
            'data' => $review
        ]);
    }

    // 📌 Delete review
    public function destroy(Product $product)
    {
        ProductReview::where('product_id', $product->id)
            ->where('user_id', Auth::id())
            ->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Review deleted'
        ]);
    }
}
Tags: Blog
Share this post

Encoderbase Team

Author

Articles and insights from the Encoderbase editorial team covering web development, software engineering, and digital solutions.

Enjoyed this article?

Get more articles like this delivered to your inbox — no spam, unsubscribe any time.

Link copied to clipboard!