Database schema & key types
Two tables back the package. reviews holds reviews and owner responses alike:
| Column | Type | Notes |
|---|---|---|
id | bigint | Auto-incrementing primary key. |
parent_id | bigint, nullable | Foreign key to reviews (null on delete) — set on owner responses. |
reviewable_type / reviewable_id | morph, nullable | The subject; id typed by key_type. |
author_type / author_id | morph, nullable | The author; id typed by key_type. |
rating | unsigned tinyint, nullable, indexed | null = a text-only review or a response. |
status | string, indexed | pending, approved or rejected; defaults to pending. |
verified | boolean, indexed | Verified purchase / reviewer; defaults to false. |
title | string, nullable | Optional headline. |
content | text, nullable | Optional body — a rating-only review has none. |
meta | jsonb, nullable | Free-form metadata, cast to a Collection; holds rejection_reason. |
helpful_count / unhelpful_count | unsigned int | Denormalized vote tallies; default 0. |
approved_at | timestamp, nullable | Stamped on approval, cleared on rejection. |
created_at / updated_at / deleted_at | timestamps | Reviews soft-delete. |
A composite index on (reviewable_type, reviewable_id, status) serves the per-subject aggregate queries. The rating column is an unsigned tiny integer, so keep max_rating at 255 or below.
review_votes
- review_id — foreign key to the configured review model’s table, cascading on delete.
- voter_type / voter_id — the polymorphic voter, typed by key_type.
- helpful — true for helpful, false for unhelpful.
- A unique index on (review_id, voter_type, voter_id): one vote per voter per review.
Key types
Authors, subjects and voters are polymorphic, so any Eloquent model can take part. key_type types their id columns; the package’s own tables always keep auto-incrementing keys:
| key_type | Use when your authors, subjects and voters… |
|---|---|
bigint | use Laravel’s default auto-incrementing keys (the default) |
uuid | use HasUuids |
ulid | use HasUlids |
All your morph targets must share one key type. Set it before you run the migrations — it is read when they run:
# Set before you run the migrations — the morph columns are typed from it
REVIEWS_KEY_TYPE=uuidAny other value throws InvalidConfigurationException instead of quietly migrating as bigint.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.