Configuration
The package works with zero published configuration — the defaults are merged in automatically. The published config/reports.php:
return [
'model' => RoundlyConsulting\Reports\Models\Report::class,
'table' => 'reports',
'key_type' => env('REPORTS_KEY_TYPE', 'bigint'),
'default_reason' => 'other',
'reasons' => ['spam', 'abuse', 'harassment', 'inappropriate', 'misinformation', 'other'],
'allow_unknown_reasons' => false,
'prevent_duplicates' => true,
'duplicate_scope' => 'open',
'strict_transitions' => true,
'threshold' => null,
'prune_after_days' => null,
'moderation' => [
'default_rule' => 'unanimous',
'default_quorum' => null,
],
];Every key
| Key | Default | Purpose |
|---|---|---|
model | Report::class | The Eloquent model that stores reports. Point it at your own Report subclass; anything else throws InvalidConfigurationException. |
table | reports | The table reports live in — read by the model and by the migration. A string; a blank value is not set, so reports applies. |
key_type | bigint | Morph key type for reporter, reported and resolved_by: bigint, uuid or ulid. Env REPORTS_KEY_TYPE; unset or blank reads as bigint, any other value throws InvalidConfigurationException. |
default_reason | other | The reason used when a report is filed without one (a string; a blank value is not set, so other applies). |
reasons | the six Reason slugs | The allowed reason slugs — a non-empty list of non-empty strings; a blank value is not set, so the Reason slugs apply. Add your own custom slugs here. |
allow_unknown_reasons | false | When true, any reason slug is accepted without validation. |
prevent_duplicates | true | Stop the same reporter or guest from reporting the same subject twice. Filings against one subject are serialized, so a double-submit can’t slip through. |
duplicate_scope | open | open dedupes against open reports only; any against every report ever filed. Any other value throws. |
strict_transitions | true | Allow only declared status transitions; illegal moves throw. |
threshold | null | ReportThresholdReached fires when a new report brings a subject’s open count to exactly this number — once per crossing. null, blank (not set) or 0 disables it; anything else that is not a whole number throws InvalidConfigurationException when a report is filed. |
prune_after_days | null | Default age in days for Reports::prune() / reports:prune when no window is given. null or blank (not set) requires one — MissingPruneWindowException, never a zero-day window; anything else that is not a whole number throws InvalidConfigurationException. |
moderation.default_rule | unanimous | Default ApprovalRule for Reports::moderate() unless ->rule() is called: unanimous, quorum, any or weighted. An unknown value throws InvalidConfigurationException when Reports::moderate() is called. |
moderation.default_quorum | null | Approval count (at least 1) of the quorum rule unless ->quorum() is called. null or blank (not set) requires every declared moderator; any other non-integer throws InvalidConfigurationException. |
The moderation block seeds the Reports::moderate() builder. An unrecognised default_rule, or a default_quorum that isn’t a whole number of at least 1, throws InvalidConfigurationException rather than falling back to the strictest setting.
Environment
Only the key type is env-backed:
REPORTS_KEY_TYPE=uuidValues read from .env arrive as strings and are read as such: the integer keys accept integer strings ('5') and the switches accept 'true'/'false', '1'/'0', 'on'/'off' and 'yes'/'no' — anything else throws. A key that is not set — absent, null, or blank like a host’s KEY= — takes its default; for the optional threshold, prune_after_days and moderation.default_quorum that means unset (no threshold, an explicit window required, every moderator), never 0. A value that is set but unusable throws the toolkit’s RoundlyConsulting\PackageToolkit\Exceptions\InvalidConfigurationException rather than quietly picking a side, and php artisan about shows it as INVALID.
- A threshold, prune_after_days or moderation.default_quorum that is not a whole number (“two”, “1.5”).
- A duplicate_scope other than open or any, or an unknown moderation.default_rule.
- A non-string table or default_reason.
- A reasons list that is empty or holds a non-string slug.
- A model that is not Report or a subclass of it.
Set table and key_type before you migrate — both are read when the migration runs. To check what is active, php artisan about includes a Reports section (see Artisan commands).
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.