hootlex/laravel-moderation
A Laravel package for moderating Eloquent models. Add moderation to any model with a trait, then approve, reject, or mark records pending using simple methods, query scopes, and events. Includes customizable status columns and support for filtering moderated content.
Architecture fit. Unchanged. The package remains a thin Moderatable trait on Eloquent models plus a polymorphic moderations table recording decision (pending/approved/rejected), moderator, and timestamps. It composes through traits, hangs off Eloquent relations, and exposes scopes and events rather than inventing a parallel abstraction — idiomatic Laravel, conceptually compatible with almost any codebase. The domain limitation is untouched: this is a binary, single-stage state machine. Multi-stage review, quorum approval, reason codes, appeals, and SLA timers still have storage primitives but no workflow.
Integration feasibility. Still the gating issue, but v1.1.0 sharpens the picture rather than changing the verdict. Two additions:
Feasibility remains conditional: viable only inside a frozen Laravel 5.5/5.6 application on PHP 7.2 or below.
Technical risk. Low complexity, high staleness — unchanged, and if anything reinforced. A release that stops at PHP 7.2 is a release that was tracking the then-current runtime; nothing in these notes addresses modern Eloquent, typed properties, return types, or helper/Str API drift. There is still no upstream maintenance signal beyond this, no security response channel, and no downstream adoption (zero registered dependents despite 528 stars). Auto-discovery slightly reduces install effort but does nothing for the "you are the maintainer the moment you install it" conclusion — it arguably makes it easier to install something you will later have to own.
Key questions. Substantively the same set, with one addition:
moderations relation, or denormalized onto the parent row for query performance?Stack fit. Conceptually strong, version-wise poor — unchanged. v1.1.0 improves the ergonomics of installing into the era it targets (auto-discovery means less boilerplate in a 5.5/5.6 app) without closing any of the distance to a modern stack. The trait-plus-polymorphic-table pattern is still exactly how a Laravel team would build this today; the shipped code is still years behind the framework it targets, and now with a declared PHP ceiling to prove it.
Migration path. Recommend adopting the design, not the dependency — this conclusion is unaffected. Reimplement as a first-party Moderatable trait with a moderations migration, an enum-backed status column, Eloquent events on transition, and a policy for who may decide. Small, well-understood build (2–4 developer-days including tests) yielding code your team can extend into multi-stage workflow later without a fork. The package serves as a reference implementation and a schema sanity check — and v1.1.0 does not change that role.
If a legacy Laravel 5.5/5.6 app must ship quickly, the pinned-install-behind-an-adapter path remains valid and is now marginally cheaper: auto-discovery removes provider wiring, so budget 1–2 days to install, audit, and wrap. The standing obligation to carry the fork is unchanged. Note the tighter floor — if the target app is on 5.0–5.4, this release does not help you and you should treat the package as pre-5.5 code with manual registration.
Compatibility. Verify in a spike before committing: Composer constraint resolution against your pinned Laravel and PHP 7.2 ceiling; behavior under package-discovery caching and config caching; scope behavior with eager loading and pagination. Do not accept "it installed" as evidence of compatibility — auto-discovery in particular makes installation look clean right up until a cached-boot path fails.
Sequencing. Unchanged:
status on the parent model for cheap filtering.Maintenance. Unchanged. An in-house trait is a few hundred lines with tests — negligible steady state, full control. A fork of an abandoned package remains the worst option: same maintenance burden plus divergence overhead from an upstream that will never merge your patches. Auto-discovery does not alter this; it only changes how the package attaches itself before you start patching it.
Support. No vendor, no active maintainer. The v1.1.0 notes are a maintenance signal from the past, not a present-tense one — do not read them as evidence of an active upstream. Community answers for a 5.5/5.6-era package will be sparse and themselves stale. Plan for internal ownership regardless of path.
Scaling. Unchanged. The write path is trivial — one row per moderation action. Scaling risk is read-side: if status is derivable only through the polymorphic relation, every "show me pending posts" query becomes a join or an N+1. Denormalize status onto the parent row and index (status, created_at) and (moderatable_type, moderatable_id). Moderation queues are low-volume and admin-facing; query shape, not throughput, is the constraint.
Failure modes.
approved() scopes that omit legacy rows created before the feature shipped.Ramp-up. Very low for any Laravel developer — hours to understand the pattern, a day to reimplement competently. v1.1.0 does not change that, and its PHP 7.2 ceiling is a useful shorthand to communicate the package's vintage to the team. The real ramp-up cost remains organizational: agreeing on the state machine and audit requirements before code exists, which is where a TPM should spend the time.
How can I help you explore Laravel packages today?