Skip to content

codebyray/laravel-review-rateable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

125 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Laravel Review Rateable

Packagist Downloads GitHub GitHub release (latest SemVer) TravisCI

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

  • 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/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' => 'sales',       // 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 approved or not approved reviews/ratings by department

// Approved reviews department with ratings
$product = Product::findOrFail($productId);

// Get approved reviews by department (with related ratings)
// Default: approved: true, withRatings: true
$product->getReviewsByDepartment("sales");

// Get not approved reviews department (with related ratings)
$product->getReviewsByDepartment("sales", false);
$product->getReviewsByDepartment(department: "sales", approved: false);

// Get approved reviews department (without related ratings)
$product->getReviewsByDepartment("sales", true, false);
$product->getReviewsByDepartment(department: "sales", withRatings: false);

Get reviews/ratings based on a star rating.

// Fetch the product
$product = Product::findOrFail($productId);

// Get approved reviews by star rating. The below call will return all 5-star 
// reviews/ratings for the "support" department.
// Defaults: starValue: null, department: "default", approved: true, withRatings: true
$product->getReviewsByRating(5, department: "support");

// If you only want the reviews and not the ratings, add withRatings: false:
$product->getReviewsByRating(5, department: "support", withRatings: false);

Get the total number of reviews.

// Approved reviews department with ratings
$product = Product::findOrFail($productId);

// Get the total number of reviews for the reviewable resource.
// Default: approved = true
$product->totalReviews();

// Get the total number of reviews for the reviewable resource by department.
// Defaults: department = "default", approved = true
$product->totalDepartmentReviews(department: "sales");

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

Count the 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();

// Get the total for a specific department
// Defaults: department: "default", approved = true
$totalDepartmentReviews = $product->totalDepartmentReviews();

Return an array of rating value ⇒ count, for the full model or for a given department.

// Retrieve a Product instance (assuming Product uses the ReviewRatable trait)
$product = Product::find($productId);

// Returns the total number of ratings. 
// Defaults: department: "default", approved = true
$totalReviews = $product->ratingCounts();

// Returns, where the array key is the star rating and the value is the total count
array:51 => 0
  2 => 1
  3 => 8
  4 => 0
  5 => 3
]

Returns a muti-denominational array with ratings stats for a given department.

// Retrieve a Product instance (assuming the Product uses the ReviewRatable trait)
$product = Product::find($productId);

// Get the stats for a given department or the default.
// Defaults: department: "default", approved = true
$totalReviews = $product->ratingStats();

// Returns, where the "counts" array holds the count for each star rating.
// And the "percentages" holds to percentage for each star rating.
// Finally, the total number of star ratings is returned.
array:3"counts" => array:5 [▶
    1 => 0
    2 => 1
    3 => 8
    4 => 0
    5 => 3
  ]
  "percentages" => array:5 [▶
    1 => 0.0
    2 => 8.0
    3 => 67.0
    4 => 0.0
    5 => 25.0
  ]
  "total" => 12
]

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

Notes

About

Review & Rating System For Laravel 10, 11 & 12

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors

Languages