oi-laravel-reviews maintained by oi-lab
OI Laravel Reviews
Reviews for Laravel — for the website itself and for any of your models. Collect a single rating or a set of coefficient-weighted criteria on one shared grid (0–5, 0–10, whatever you configure), moderate submissions, publish an official reply to the reviews that are not in your favour, and send confirmation, thank-you and reply emails whose copy is stored in oi-lab/oi-laravel-settings so it stays editable at runtime.
Features
- Two review models:
ReviewWebsitefor the site,ReviewEntryfor any polymorphicreviewablemodel (restricted to a configurable allow-list). - A single evaluation grid shared by every review and every criterion —
switch it from
/5to/10in config. - Criteria defined in config (title, description, coefficient); the overall rating is the coefficient-weighted average of the per-criterion scores, or a single direct rating when no criteria are declared.
- Guest or authenticated authors, with per-scope moderation
(
pending → approved / rejected) and anauto_approveshortcut. - One official
ReviewReplyper review, moderated on the same scale. - Lifecycle emails (
confirmation,thank_you,reply) rendered frommail-typed settings, personalised with:placeholders, optionally queued. - Typed spatie/laravel-data DTOs for
every model, config-gated JSON routes, form requests, services and a
Reviewsfacade. - Lifecycle events (
ReviewSubmitted,ReviewApproved,ReviewReplied) and fully swappable models resolved through a static resolver.
How It Works
A review is scored on one grid. Leave criteria empty and a review is just an
overall rating. Declare criteria and each is scored individually — the package
stores a ReviewRating row per criterion and writes the coefficient-weighted
average into the review's rating column, so listings and averages stay a
single indexed number. ReviewWebsite and ReviewEntry share the same
behaviour; only ReviewEntry adds the polymorphic reviewable link. Every
ratings row and the single ReviewReply attach to their review polymorphically,
so both review types reuse them.
Requirements
- PHP 8.2+
- Laravel 11, 12, or 13
- spatie/laravel-data 4.23+
- oi-lab/oi-laravel-settings 1.0+ (mail templates)
Installation
composer require oi-lab/oi-laravel-reviews
Publish & Migrate
php artisan vendor:publish --tag=oi-laravel-reviews-config
php artisan vendor:publish --tag=oi-laravel-reviews-migrations
php artisan migrate
# seed the notification mail templates into the settings store
php artisan reviews:install-settings
Optionally publish the email view to restyle it:
php artisan vendor:publish --tag=oi-laravel-reviews-views
Configuration
config/oi-laravel-reviews.php (excerpt):
'grid' => [
'min' => 0,
'max' => 5, // set to 10 for a /10 grid
'step' => 0.5, // null to allow any value in range
],
'moderation' => [
'auto_approve' => false,
],
// Models a ReviewEntry may target, keyed by the alias used in requests
'reviewable_models' => [
'product' => \App\Models\Product::class,
],
// Criteria are config, not database rows. Empty = a single overall rating.
'criteria' => [
'website' => [
'design' => ['title' => 'Design', 'description' => '', 'coefficient' => 1],
'support' => ['title' => 'Support', 'description' => '', 'coefficient' => 2],
],
'entries' => [
'default' => [
'value' => ['title' => 'Value for money', 'description' => '', 'coefficient' => 1],
],
'product' => [
'taste' => ['title' => 'Taste', 'description' => '', 'coefficient' => 2],
],
],
],
'notifications' => [
'enabled' => true,
'queue' => true,
'settings' => [
'confirmation' => 'reviews.mail.confirmation',
'thank_you' => 'reviews.mail.thank_you',
'reply' => 'reviews.mail.reply',
],
],
Usage
Submit a website review
use OiLab\OiLaravelReviews\Facades\Reviews;
$review = Reviews::submitWebsiteReview([
'rating' => 4.5,
'title' => 'A pleasure to use',
'body' => 'Fast and clear.',
'author_name' => 'Jo',
'author_email' => 'jo@example.com',
]);
Submit a review of one of your models (with criteria)
$review = Reviews::submitEntryReview(
'product', // reviewable alias from config
$product->id,
['author_name' => 'Jo', 'author_email' => 'jo@example.com'],
['taste' => 4, 'value' => 5], // criterion key => score
);
$review->rating; // coefficient-weighted average of the criteria
Pass an authenticated user as the last argument to record them as the author instead of a guest:
Reviews::submitWebsiteReview(['rating' => 5], [], $request->user());
Moderate and reply
Reviews::approve($review); // publishes it and emails a thank-you
Reviews::reject($review);
use OiLab\OiLaravelReviews\Services\ReviewReplyService;
app(ReviewReplyService::class)->reply($review, [
'body' => 'Thanks for the feedback — here is what happened.',
'author_name' => 'Support',
]);
JSON endpoints
Loaded under route.prefix (default reviews) when route.enabled is true:
| Method & URI | Purpose |
|---|---|
GET reviews/website |
Approved website reviews + summary (count, average) |
POST reviews/website |
Submit a website review |
GET reviews/entries?reviewable_type=&reviewable_id= |
Approved reviews for a model |
POST reviews/entries |
Submit an entry review |
POST reviews/website/{uuid}/reply |
Reply to a website review |
POST reviews/entries/{uuid}/reply |
Reply to an entry review |
The reply routes honour the optional route.gate.
Events
Listen instead of overriding internals:
OiLab\OiLaravelReviews\Events\ReviewSubmittedOiLab\OiLaravelReviews\Events\ReviewApprovedOiLab\OiLaravelReviews\Events\ReviewReplied
Notification Emails
Each lifecycle email resolves a MailContent from a mail-typed setting in
oi-lab/oi-laravel-settings, falling back to notifications.defaults when the
setting is unset. reviews:install-settings seeds those settings; edit them at
runtime to change the copy. Placeholders (:author, :title, :rating,
:reply) are substituted per message, and delivery is queued when
notifications.queue is true.
Customizing Models
Every model is resolved through OiLab\OiLaravelReviews\OiLaravelReviews. Point
models.* in the config at your own subclasses to add relations or behaviour
without forking the package.
AI Assistant Skills
This package ships an AI-assistant skill. Install it into your project:
php artisan oi:install-ai-skill
Testing
composer test
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
When contributing:
- Write tests for new features
- Ensure all tests pass:
vendor/bin/pest - Follow existing code style
- Update documentation as needed
License
The MIT License (MIT). Please see the License File for more information.
Credits
Olivier Lacombe - Creator and maintainer
Olivier is a Product & Technology Director based in Montpellier, France, with over 20 years of experience innovating in UX/UI and emerging technologies. He specializes in guiding enterprises toward cutting-edge digital solutions, combining user-centered design with continuous optimization and artificial intelligence integration.
Projects & Resources:
- OI Dev Docs - Documentation for all Open Source OI Lab packages
- OnAI - Training courses and masterclasses on generative AI for businesses
- Promptr - Prompt engineering Management Platform
Support
For support, please open an issue on the GitHub repository.