NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Reviews for Laravel

Database schema & key types

Two tables back the package. reviews holds reviews and owner responses alike:

ColumnTypeNotes
idbigintAuto-incrementing primary key.
parent_idbigint, nullableForeign key to reviews (null on delete) — set on owner responses.
reviewable_type / reviewable_idmorph, nullableThe subject; id typed by key_type.
author_type / author_idmorph, nullableThe author; id typed by key_type.
ratingunsigned tinyint, nullable, indexednull = a text-only review or a response.
statusstring, indexedpending, approved or rejected; defaults to pending.
verifiedboolean, indexedVerified purchase / reviewer; defaults to false.
titlestring, nullableOptional headline.
contenttext, nullableOptional body — a rating-only review has none.
metajsonb, nullableFree-form metadata, cast to a Collection; holds rejection_reason.
helpful_count / unhelpful_countunsigned intDenormalized vote tallies; default 0.
approved_attimestamp, nullableStamped on approval, cleared on rejection.
created_at / updated_at / deleted_attimestampsReviews 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_typeUse when your authors, subjects and voters…
bigintuse Laravel’s default auto-incrementing keys (the default)
uuiduse HasUuids
uliduse 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=uuid

Any 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 crypto

By 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.