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

Reporting & auto-moderation

Comments are a report subject via Reports for Laravel (Comment implements Reportable): flag abusive or spam comments with dedup, typed reasons and guest reports. Reporters are always passed explicitly:

use RoundlyConsulting\Reports\Facades\Reports;

Reports::report($comment)->by($user)->for('spam')->create();
Reports::report($comment)->asGuest($fingerprint)->for('abuse')->create();

$comment->hasBeenReported();
$comment->isReportedBy($user);

Moderation queue

// Moderation queue on the CommentQuery builder:
Comments::for($post)->mostReported()->get();
Comments::for($post)->reportedMoreThan(3)->get();
Comments::for($post)->withReportCounts()->get(); // each row: ->reports_count

Auto-hide

When a report is upheld (ReportResolved) or a comment crosses the global reports.threshold (ReportThresholdReached), the SyncCommentVisibilityFromReports listener hides the comment — its status becomes hidden and CommentHidden is dispatched, just like a manual hide. It ignores non-comment subjects and only acts on a currently approved comment, so it never hides twice. Both paths are config-gated:

// config/comments.php
'moderation' => [
    'on_resolved' => 'hide', // null disables the upheld-report path
    'auto_hide' => true,     // false ignores ReportThresholdReached
],

The threshold path only fires when reports.threshold is set in the Reports config — it is null (off) there by default.

Multi-moderator sign-off

Reports routes resolution through Approvals for Laravel, so requiring several moderators takes no extra code. Moderators are saved Eloquent models — typically your User with the Approvals GivesApprovals trait (implements GivesApprovalsInterface), which adds its givenApprovals() relation:

use RoundlyConsulting\Approvals\Enums\ApprovalRule;
use RoundlyConsulting\Reports\Exceptions\ModeratorRequiredException;
use RoundlyConsulting\Reports\Facades\Reports;

Reports::moderate($report)->requiring([$alice, $bob])->rule(ApprovalRule::Quorum)->quorum(2)->open();
Reports::resolve($report, by: $alice);           // 1/2 — comment stays visible
Reports::resolve($report, by: $mallory);         // not named → ModeratorRequiredException, nothing recorded
Reports::resolve($report, by: $bob);             // quorum reached → comment hidden

Only the moderators named in requiring([...]) — or an Approvals delegate of one — can decide while the request is open; anyone else, and a call without by:, is refused with Reports’ ModeratorRequiredException.

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.