codebyray / laravel-review-rateable
Review & Rating system for Laravel 10, 11 & 12
Fund package maintenance!
codebyray
Installs: 337 632
Dependents: 0
Suggesters: 0
Security: 0
Stars: 299
Watchers: 3
Forks: 56
Open Issues: 5
Requires
- php: >=8.1
- illuminate/config: ^10.0 || ^11.0 || ^12.0
- illuminate/database: ^10.0 || ^11.0 || ^12.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0
Requires (Dev)
- orchestra/testbench: ^6.23 || ^7.0 || ^8.0 || ^9.0 || ^10.0
- pestphp/pest: ^1.20 || ^2.0 || ^3.0
README
NOTE: This is a complete rewrite from v1. It is not compatible with previous versions of this package.
Laravel Review Ratable is a flexible package that enables you to attach reviews (with multiple ratings) to any Eloquent model in your Laravel application. The package supports multiple departments, configurable rating boundaries, review approval, and a decoupled service contract so you can easily integrate, test, and extend the functionality.
Features
- Polymorphic Reviews & Ratings: Attach written reviews along with multiple rating values to any model.
- Configurable Settings: Define custom rating keys, labels, and value boundaries (min/max) via a config file.
- Department Support: Organize ratings by department (e.g. default, sales, support) with their own criteria.
- Review Approval: Set a default approval status for reviews (and override per review if needed).
- Flexible Data Retrieval: Retrieve reviews with or without ratings, filter by approval status, and calculate averages.
- Service Contract: Use a dedicated service that implements a contract for a decoupled, testable API.
Requirements
- PHP 8.1 or higher
- Laravel 10, 11, or 12
Installation
1. Install via Composer
In your Laravel application's root, require the package via Composer.
composer require codebyray/laravel-review-rateable:^2.0
2. Publish Package Assets
After installation, publish the package config and migration files:
php artisan vendor:publish --provider="Codebyray\ReviewRateable\ReviewRateableServiceProvider" --tag=config
php artisan vendor:publish --provider="Codebyray\ReviewRateable\ReviewRateableServiceProvider" --tag=migrations
Run the migrations to create the necessary database tables:
php artisan migrate
Configuration
The package configuration file is located at config/laravel-review-ratable.php. Here you can adjust global settings such as:
- Rating Value Boundaries:
- min_rating_value: Minimum rating value.
- max_rating_value: Maximum rating value.
- Review Approval:
- review_approved: Default approval status for new reviews.
- Departments & Rating Labels: Define multiple departments, each with its own set of rating keys and labels.
Example configuration:
<?php return [ 'min_rating_value' => 1, 'max_rating_value' => 10, 'review_approved' => false, // Reviews will be unapproved by default 'departments' => [ 'default' => [ 'ratings' => [ 'overall' => 'Overall Rating', 'customer_service' => 'Customer Service Rating', 'quality' => 'Quality Rating', 'price' => 'Price Rating', 'recommendation' => 'Would Recommend?', ], ], 'sales' => [ 'ratings' => [ 'overall' => 'Overall Rating', 'communication' => 'Communication Rating', 'follow_up' => 'Follow-Up Rating', 'recommendation' => 'Would Recommend?', ], ], 'support' => [ 'ratings' => [ 'overall' => 'Overall Rating', 'speed' => 'Response Speed', 'knowledge' => 'Knowledge Rating', 'recommendation' => 'Would Recommend?', ], ], ], ];
Usage
Making a Model Reviewable
To allow a model to be reviewed, add the ReviewRateable
trait to your model. For example, in your Product
model:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Codebyray\ReviewRateable\Traits\ReviewRateable; class Product extends Model { use ReviewRateable; }
Adding a review/rating(s)
You can add a review (with ratings) directly via the trait:
$product = Product::find($productId); $product->addReview([ 'review' => 'Great product! The quality is superb and customer service was excellent.', 'department' => 'sales', // Optional, defaults to 'default' 'recommend' => true, // Whether the user would recommend the product being reviewed 'approved' => true, // Optionally override default (false) approval by providing 'approved' 'ratings' => [ 'overall' => 5, 'communication' => 5, 'follow_up' => 5, 'price' => 5, ], ], auth()->id());
Update a review/rating(s)
// Retrieve the product you want to update the review for. $product = Product::findOrFail($productId); // Prepare the updated data. $data = [ 'review' => 'Updated review text', // New review text. 'department' => 'default', // Optionally, change the department. 'recommend' => false, // Update recommendation flag. 'approved' => true, // Update approval status if needed. 'ratings' => [ 'overall' => 4, 'communication' => 3, 'follow_up' => 4, 'price' => 2, ], ]; // Call the updateReview method on the product. $product->updateReview($reviewId, $data);
Marking review as approved
// Retrieve the product you want to mark as approved $product = Product::findOrFail($productId); // Approve th review $product->approveReview($reviewId);
Delete a review/rating:
// Retrieve the product with the review you want to delete $product = Product::findOrFail(1); // Delete the review $product->deleteReview($reviewId);
Fetch approved or not approved reviews/ratings for a particular resource
// Approved reviews with ratings $product = Product::findOrFail($productId); // Get approved reviews (with related ratings) // Default: approved = true, withRatings = true $product->getReviews(); // Get not approved reviews (with related ratings) $product->getReviews(false); $product->getReviews(approved: false); // Get approved reviews (without related ratings) $product->getReviews(true, false); $product->getReviews(withRatings: false);
Fetch the average rating:
// Retrieve a Product instance (assuming Product uses the ReviewRatable trait) $product = Product::findOrFail($productId); // Get the average rating for a specific key ('overall') using approved reviews (default). $overallAverage = $product->averageRating('overall'); echo "Overall Average (approved): {$overallAverage}\n"; // Get the average rating for a specific key using non-approved reviews. $nonApprovedOverall = $product->averageRating('overall', false); echo "Overall Average (pending): {$nonApprovedOverall}\n"; // Get all average ratings for all rating keys from approved reviews. $allAverages = $product->averageRatings(); // Returns something like [ "overall" => 3.5, "communication" => 2.75, "follow_up" => 3.5, "price" => 4.25 ] // Get the overall average rating across all ratings (approved reviews by default). $overallRating = $product->overallAverageRating(); // Returns float 3.5
Get all reviews with or without ratings:
// Retrieve a Product instance (assuming Product uses the ReviewRatable trait) $product = Product::find($productId); // Get all approved reviews with their ratings eager loaded. $reviewsWithRatings = $product->getReviews(true, true); // Get all approved reviews without eager loading ratings. $reviewsWithoutRatings = $product->getReviews(true, false);
Count total number of reviews:
// Retrieve a Product instance (assuming Product uses the ReviewRatable trait) $product = Product::find($productId); // Returns the total number of reviews. $totalReviews = $product->totalReviews();
Example Usage in a Controller
Every method available using the ReviewRateable Trait can also be called via the service
<?php namespace App\Http\Controllers; use App\Models\Product; use CodeByRay\LaravelReviewRatable\Contracts\ReviewRatableContract; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; class ProductReviewController extends Controller { protected ReviewRatableContract $reviewService; public function __construct(ReviewRatableContract $reviewService) { $this->reviewService = $reviewService; } public function store(Request $request): JsonResponse { $product = Product::find($request->input('product_id')); $this->reviewService->setModel($product); $data = [ 'review' => $request->input('review'), 'department' => $request->input('department'), 'recommend' => $request->boolean('recommend'), // 'approved' is optional and will default to config value. 'ratings' => [ "overall" => $request->input('overall'), "communication" => $request->input('communication'), "follow_up" => $request->input('follow_up'), "price" => $request->input('price') ]), ]; $review = $this->reviewService->addReview($data, auth()->id()); return response()->json(['message' => 'Review added!', 'review' => $review]); } public function show(Product $product): JsonResponse { $this->reviewService->setModel($product); $reviews = $this->reviewService->getReviews(); // Get approved reviews with ratings $total = $this->reviewService->totalReviews(); return response()->json(compact('reviews', 'total')); } }
Testing
composer test