flarum/flags
Flarum extension that lets moderators flag posts for review, adding a dedicated flags list and permission controls for reviewing and resolving flagged content.
This is a Flarum extension, not a general-purpose Laravel package. You are working inside Flarum's container and extension API — Illuminate database, events, and validation are available, but there is no app/Http/Kernel.php, no routes/web.php, and no php artisan.
# already bundled with flarum/core in most installs — check first
composer show flarum/flags
# only if it's genuinely absent
composer require flarum/flags
php flarum extend:enable flarum-flags
php flarum cache:clear
Where to look first (in order):
extend.php — the whole integration surface: API routes (POST|DELETE /api/posts/{id}/flags), the Flag model, serializers, and permission registrations.src/Flag.php and src/Command/ — the flag entity and the flag/unflag command handlers.src/Event/ — Flagging (pre-persist) and Flagged (post-persist); these are your primary hooks.js/src/forum/ — the flag button, the flag-reason modal, and the moderator flag list page. js/src/admin/ — permission labels.First use case: grant discussion.flagPosts to members and discussion.viewFlags to moderators in the admin Permissions tab, then confirm a flag round-trips: flag a post on the frontend, open the moderator flag list, and GET /api/flags?include=user,post with a token to see the raw payload. That single end-to-end pass validates permissions, serializer output, and event wiring in one go.
React to flags in your own extension via events — the cleanest integration point, no core edits:
use Flarum\Flags\Event\Flagged;
use Flarum\Extend;
return [
(new Extend\Event())
->listen(Flagged::class, function (Flagged $event) {
$flag = $event->flag; // Flag model, already persisted
// push to Slack, bump a report counter, write an audit row
}),
];
Keep listeners fast — Flarum dispatches these synchronously inside the request. Anything network-bound belongs in a queued job dispatched from the listener.
Auto-hide after N flags — count distinct flaggers in your Flagged listener and dispatch Flarum's hide command (Flarum\Post\Command\HidePost) through the command bus using a moderator/system actor. Verify the command's constructor in flarum/core before wiring it; treat this as the canonical "moderation automation" pattern rather than reaching for raw SQL.
Expose extra flag data to the frontend — extend the serializer rather than shipping a parallel endpoint:
(new Extend\ApiSerializer(\Flarum\Flags\Api\FlagSerializer::class))
->attribute('riskScore', fn ($serializer, $flag) => /* ... */);
Same approach works for adding includes or tightening visibility with Extend\ApiController on the flag list/show controllers.
Custom moderation dashboard — consume GET /api/flags?include=user,post&page[limit]=25 with a token scoped to a moderator account. The post include is what you need to render title/discussion context; request post.discussion explicitly if you want it, since includes are not deep by default. Filter and sort server-side where the resource supports it instead of pulling everything and filtering in JavaScript.
Frontend extension — from your own extension's js/src/forum/index.js, import { extend } from 'flarum/common/extend' and hook the flag button/modal components (js/src/forum/components). Overriding the reason list is common; overriding the whole flag flow is a maintenance liability across upgrades.
System/automated flags — create flags with an explicit actor (a dedicated bot user) so the user relationship is populated. Flags without a user render as broken rows in most moderator UIs and break include=user assumptions in downstream tooling.
flarum/core. Never relax the flarum/core constraint in composer.json to force an install — you'll get serializer/route mismatches that only show up at runtime.js/dist). Changing js/src in a vendored copy does nothing until you rebuild (cd js && npm ci && npm run build). If you're extending the frontend, do it from your own extension so composer update doesn't silently wipe your edits.(user_id, post_id) in your own listener before acting on thresholds.post relationship and user relationship can both be null after deletions. Guard every access — especially in serializers and custom API resources, where a null dereference becomes a 500 for the whole list.extend.php or permissions, run php flarum cache:clear and restart queue workers. "My listener isn't firing" is almost always stale cached code or a listener registered from an extension that isn't enabled.flags table directly for moderator-facing features — you'll bypass visibility rules and leak flags across permission boundaries. Go through the model, policies, and the API resource.reasonDetail short. It's intended as a free-text adjunct to a short reason category; if you're storing structured payloads there, you're fighting the schema and every UI that renders flags.storage/logs/ for Flarum's Monolog output and use php flarum info to confirm the extension is enabled and its version matches core. For API-level issues, hit the endpoint with an explicit token — permission failures on flags are silent-ish (fields simply disappear from the payload) rather than loudly erroring, so a 200 with missing attributes usually means a permission problem, not a serializer bug.How can I help you explore Laravel packages today?