Every report carries a reason slug, validated against config('reports.reasons'). A disallowed slug throws UnknownReportReasonException unless allow_unknown_reasons is true. The defaults map to the Reason enum:
| Case | Slug | Label |
|---|---|---|
Reason::Spam | spam | Spam |
Reason::Abuse | abuse | Abuse |
Reason::Harassment | harassment | Harassment |
Reason::Inappropriate | inappropriate | Inappropriate |
Reason::Misinformation | misinformation | Misinformation |
Reason::Other | other | Other |
Labels and options
Reason adopts the Helpers trait from enums-for-laravel, so labels, values and select options come ready-made:
use RoundlyConsulting\Reports\Enums\Reason;
Reason::Abuse->label(); // "Abuse"
Reason::Inappropriate->readable(); // "Inappropriate"
Reason::values(); // Collection: 'spam', 'abuse', 'harassment', …
Reason::validationRule(); // "in:spam,abuse,harassment,inappropriate,misinformation,other"
Reason::toOptions(); // Collection: ['spam' => 'Spam', 'abuse' => 'Abuse', …]Labels derive from the slug via Str::headline() and pass through Laravel’s translator, so a JSON language file can reword them.
Custom reasons
Add your own slugs to the reasons list — they are validated exactly like the built-in ones:
// config/reports.php
'default_reason' => 'other',
'reasons' => ['spam', 'abuse', 'harassment', 'inappropriate', 'misinformation', 'other', 'copyright'],
'allow_unknown_reasons' => false,Custom slugs have no enum case, so pass them as strings: ->for('copyright'). Set allow_unknown_reasons to true to accept any slug without validation.
Validating input
Reason::validationRule() covers the enum cases only. Once you add custom slugs, validate against the keys of Reports::reasons(), which returns the configured slugs with their labels:
use Illuminate\Validation\Rule;
use RoundlyConsulting\Reports\Enums\Reason;
use RoundlyConsulting\Reports\Facades\Reports;
// Enum cases only:
$request->validate(['reason' => ['required', Reason::validationRule()]]);
// Everything in config('reports.reasons'), custom slugs included:
$request->validate(['reason' => ['required', Rule::in(array_keys(Reports::reasons()))]]);Reading the allowed reasons
Ask the facade for the allowed set — ready for a select box:
use RoundlyConsulting\Reports\Facades\Reports;
Reports::reasons(); // ['spam' => 'Spam', 'abuse' => 'Abuse', …] — slug => label
Reports::reasonLabel('spam'); // "Spam" (a custom slug labels as itself)
Reports::defaultReason(); // "other"
Reports::allowsReason('copyright'); // false unless configured or allow_unknown_reasons
// A <select> straight from config, custom slugs included:
foreach (Reports::reasons() as $slug => $label) {
// <option value="{{ $slug }}">{{ $label }}</option>
}Behind these reads sits the ReasonRegistry container singleton, which you can resolve directly too:
use RoundlyConsulting\Reports\Support\ReasonRegistry;
$registry = app(ReasonRegistry::class);
$registry->all(); // list<string> — the slugs; the Reason cases when reasons is unset
$registry->isAllowed('copyright'); // bool — always true when allow_unknown_reasons is on
$registry->allowsUnknown(); // boolShow 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.