Events

Meerkat provides:

  • Meerkat events: CommentSubmitted and CommentSaved
  • Statamic form events: FormSubmitted and SubmissionCreated

Use events for notifications, audit logs, and search indexing. Use hooks to change comments during a save.

#Meerkat events

#CommentSubmitted

Fires after spam checks and before Meerkat saves a comment. Return false to discard the submission silently.

1namespace App\Listeners;
2
3use Stillat\Meerkat\Events\CommentSubmitted;
4
5class BlockBannedDomains
6{
7 public function handle(CommentSubmitted $event): bool
8 {
9 $email = $event->comment->resolvedEmail();
10 $domain = substr(strrchr($email, '@'), 1);
11
12 if (in_array($domain, ['spammer.example', 'banned.example'])) {
13 return false;
14 }
15
16 return true;
17 }
18}

Register it in App\Providers\EventServiceProvider:

1protected $listen = [
2 CommentSubmitted::class => [
3 BlockBannedDomains::class,
4 ],
5];

$event->comment contains the comment before it is saved. Any changes are saved with it.

#CommentSaved

Fires after a comment is created or edited. A frontend submission fires it once. Returning false does not cancel the completed save.

1namespace App\Listeners;
2
3use Stillat\Meerkat\Events\CommentSaved;
4
5class IndexCommentForSearch
6{
7 public function __construct(private SearchService $search) {}
8
9 public function handle(CommentSaved $event): void
10 {
11 $this->search->index($event->comment);
12 }
13}

Use CommentSaved for notifications, indexing, audit logs, and queued work. Use the model's saved hook to change what happens when the model saves.

#Listening to every Meerkat event

1use Illuminate\Support\Facades\Event;
2
3public function boot(): void
4{
5 parent::boot();
6
7 Event::listen(['Stillat\Meerkat\Events\*'], function ($eventName, $payload) {
8 logger()->info('Meerkat event', ['name' => $eventName, 'payload' => $payload]);
9 });
10}

#Statamic form events

Valid submissions fire Statamic's standard form events. Rejected submissions do not reach them.

Event When Can halt? Payload
Statamic\Events\FormSubmitted Before the comment is saved, after basic validation. Yes. return false for a silent failure, or throw a ValidationException for field errors. Statamic\Contracts\Forms\Submission
Statamic\Events\SubmissionCreated After a successful save. No. The same Submission, updated with the saved state.

#The submission object

Both events receive a Statamic\Forms\Submission whose form:

  • form()->handle() is 'meerkat'. Filter on this value if your listener also processes other forms.
  • form()->title() is 'Meerkat Comments'.
  • data() contains the submitted fields without Meerkat-only values.

Meerkat does not store comments as Statamic form submissions.

#Listen only for Meerkat forms

A listener bound to all FormSubmitted events should ignore other forms:

1use Statamic\Events\FormSubmitted;
2
3Event::listen(FormSubmitted::class, function (FormSubmitted $event) {
4 if ($event->submission->form()->handle() !== 'meerkat') {
5 return;
6 }
7});

#Validate submissions or add captcha

A FormSubmitted listener can return false to reject silently or throw a ValidationException to populate {{ errors }}. Use the meerkat-form-submit middleware group when validation must run before Meerkat's rate limiter and spam guards.

#Send a webhook after saving

1Event::listen(SubmissionCreated::class, function (SubmissionCreated $event) {
2 if ($event->submission->form()->handle() !== 'meerkat') return;
3
4 Http::post(config('services.slack.webhook'), [
5 'text' => 'New comment from '.$event->submission->data()->get('name'),
6 ]);
7});

SubmissionCreated fires only after Meerkat saves a comment.

#Change submitted values

A FormSubmitted listener can change submitted values before Meerkat saves them:

Submission field that you write Storage location on the comment
comment $comment->comment_text
name $comment->author_name
email $comment->author_email
anything else (new or changed keys) merged into $comment->comment_data

Unchanged fields are not copied into comment_data.

1Event::listen(FormSubmitted::class, function (FormSubmitted $event) {
2 if ($event->submission->form()->handle() !== 'meerkat') return;
3
4 $cleaned = strip_tags(trim($event->submission->data()->get('comment')));
5 $event->submission->set('comment', $cleaned);
6});

Limitations:

  • author_id changes are ignored. Set it in a before-saving-comment hook.
  • forget() does not clear comment fields. Set the value to null or an empty string.
  • before-saving-comment runs afterward and wins on conflicts.

#Save order

When a user submits a comment, events and hooks run in this order:

11. creatingComment ← Meerkat hook, after validation/spam checks
22. FormSubmitted ← Statamic, can halt
33. Copy changed submission values to the comment
44. CommentSubmitted ← Meerkat, can halt
55. before-saving-comment ← Meerkat hook (runs after the sync, so it wins on conflicts)
66. Comment model saving ← Meerkat model hook
77. $comment->save()
88. CommentSaved ← Meerkat saved event
99. Comment model saved ← Meerkat model hook
1010. after-saved-comment ← Meerkat hook
1111. SubmissionCreated ← Statamic

#Choose an event or hook

What you want to do Use
Notify, index, or log a comment after it saves CommentSaved
Reject a submission CommentSubmitted (or FormSubmitted), via return false
Connect a Statamic form addon (captcha, CRM, webhooks) FormSubmitted / SubmissionCreated
Change submitted fields a FormSubmitted listener (changes copy back to the comment)
Change the comment model or set the final author_id a before-saving-comment hook

#Run listeners in the background

Queue listeners that call external services:

1class IndexCommentForSearch implements ShouldQueue
2{
3 use InteractsWithQueue;
4
5 public function handle(CommentSaved $event): void
6 {
7 SearchIndex::add($event->comment);
8 }
9}

Meerkat jobs use the queue connection at config('meerkat.jobs.connection'). Your listeners use the standard Laravel queue configuration at config('queue.default').

Was this page helpful?