Open source
Reports for Laravel
composer require roundly-consulting/reports-for-laravelOverview
A content-moderation and flagging foundation for Laravel. Let any model file reports — or let guests report anonymously — against any reportable model, tag each report with a typed reason and move it through a guarded status lifecycle, with optional multi-moderator sign-off. Duplicate prevention, aggregation scopes, threshold escalation and lifecycle events come built in, behind a fluent facade with Action classes and DTOs underneath. Native and MIT-licensed, it builds only on Laravel and our own approvals, enums and package-toolkit packages — no third-party dependencies.
What you get
Report anything, from anyone
GivesReports and HasReports turn any Eloquent model into a reporter or a reportable subject — guests can report too, keyed by a hashed identifier.
Typed, extensible reasons
A Reason enum with ready-made labels and select options, plus your own custom slugs validated against a config allow-list.
Guarded status lifecycle
Pending → in review → resolved or rejected → closed, enforced by a transition table that records who settled each report, when and why.
Multi-moderator sign-off
Route decisions through approvals-for-laravel — unanimous, quorum, any or weighted — and the report settles itself once the bar is met.
Duplicate prevention & insights
Block repeat reports from the same reporter or guest, count reports per subject and sort content by most reported.
Threshold escalation & events
ReportThresholdReached fires when a subject hits your threshold, alongside events for every creation, status change and decision.
Facade, DI or actions
One Reports facade, the injectable ReportsManager or six single-purpose actions — and a recording Reports::fake() for your tests.
Documentation
Installation
Install via Composer, publish the config if you change the table or key type, then publish and run the publish-only reports and approvals migrations.
Configuration
Every config key and its default — model, table, key type, reasons, duplicate prevention, strict transitions, threshold, pruning and moderation.
Database schema & key types
The reports table column by column, its indexes, and how key_type types the morph columns for bigint, UUID or ULID models.
Preparing your models
Add GivesReports to models that file reports and HasReports to models that can be reported; Reporter and Reportable are optional markers.
The Reports facade
One facade for filing, reviewing, settling, moderating and pruning reports, plus the reason reads — with builders for filing and moderation.
DI, actions & DTOs
Inject ReportsManager instead of calling the facade, or run one of six Action classes with readonly DTOs from jobs and services.
Filing reports
File reports through the fluent Reports facade or the GivesReports trait — subject, reporter, typed reason and description in one chain.
Guest & anonymous reports
Accept reports from visitors who aren’t signed in, deduplicated by a hashed IP or email identifier.
Reasons
Typed report reasons via the Reason enum, custom slugs in config, and the facade’s reason reads — slug => label, defaults and allow checks.
Status lifecycle
Five statuses and a transition table — move reports with Reports::review(), close() or changeStatus(), guarded by strict_transitions.
Resolving & rejecting
Settle a report with Reports::resolve() or reject(), recording the moderator, a timestamp and a note, and firing the matching event.
Multi-moderator moderation
Require several moderators to sign off — unanimous, quorum, any or weighted — before a report settles, powered by approvals-for-laravel.
Duplicate prevention
Stop the same reporter or guest from reporting a subject twice — scoped to open reports or to every report ever filed.
Aggregation & querying
Count reports per subject, check who reported what, and sort or filter subjects by report count with ready-made scopes.
Threshold auto-actions
Fire ReportThresholdReached when a subject’s open report count hits your threshold — auto-hide content, alert moderators, or both.
The Report model
Report attributes, relations, scopes and soft deletes — and how to swap in your own Report subclass.
Events
Five events cover creation, status changes, resolution, rejection and threshold crossings — the same whether settled directly or via moderation.
Artisan commands
Prune old settled reports, list per-subject open report counts, and inspect the active configuration with php artisan about.
Exceptions
The typed exceptions the package throws — all extending ReportsException — and the context each one carries.
Testing
Reports::fake() records every mutating call instead of running it, with an assertion per verb — plus a factory state for every lifecycle stage.
Requirements
PHP 8.4+ and Laravel 12 or 13; approvals, enums and package-toolkit are installed automatically as dependencies.
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.