Events
Meerkat provides:
- Meerkat events:
CommentSubmittedandCommentSaved - Statamic form events:
FormSubmittedandSubmissionCreated
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_idchanges are ignored. Set it in abefore-saving-commenthook.forget()does not clear comment fields. Set the value tonullor an empty string.before-saving-commentruns 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').