Event Listeners for Statamic

March 9, 2022 · 5 min read

2025 UPDATE
We have updated this blog post to include the new features available up to 2025 since its original publication in 2020.
Laravel and Statamic Event Listeners
Laravel’s event-driven architecture lets developers add custom features by tapping into the framework’s core. Statamic, a flat-file CMS built on top of Laravel, takes advantage of this by offering events that you can use to make your web app better. These events are related to all the main parts of Statamic like Assets, Blueprints, Collections, Entries, Forms, Taxonomies, Users, and more. They are triggered when you do actions like create, delete, update, upload, or find content on your Statamic site.
Understanding Statamic Event
Events in Statamic are dispatched in response to specific changes within the CMS. For example, when you add or update content, events like EntrySaved or EntrySaving are triggered. These are important for developers who want to run custom code during certain events in the content management process. By using these events, you can do things like update external databases, integrate with third-party services, or modify how the CMS works.
Implement a Fuzzy Search feature with Fuse.js
You can use Statamic events to add special search features. Statamic’s built-in search is good, but it might not work for everything, like searching for text in alphabets like Cyrillic. You can use a fuzzy-search library like Fuse.js to enable approximate string matching. This is really helpful for big projects or when you need more flexible search criteria. We explain how to use Fuse.js with Statamic to get fuzzy searching on your website. For large projects, we often suggest using Algolia with Statamic.
Create the event listener
To make it work, we need to create an event listener that will handle the event. The listener can be created with the following command and it will be found at app/Listeners.
php artisan make:listener SavePostsToJsonIn our example, we want to create a JSON file that stores the title, categories, and tags of all posts. We need to create an event listener that will refresh the JSON data whenever we add a new post. When we save an entry, the event EntrySaved is triggered. Then, we can use the data from that entry to do things we need. Here’s what you get after creating the listener:
use Statamic\Events\EntrySaved;
public function handle(EntrySaved $event)
{
$event->entry;
}Query all posts
Let’s get back to our event listener. We mentioned that we want to query all posts and that’s why we need to include the Entry Facade. The saved data will be added to a new json file that will be located in the public directory.
namespace App\Listeners;
use Statamic\Facades\Entry;
use Statamic\Events\EntrySaved;
class SavePostsToJson
{
public function handle(EntrySaved $event)
{
$data = Entry::query()
->where('collection', 'posts')
->get()
->transform(function ($post) {
return [
'title' => $post->title,
'categories' => $post->categories,
'slug' => (string)$post->slug()
];
})
->toArray();
file_put_contents(public_path() . '/search/data.json', json_encode($data));
}
}That’s it, we can now create a new post and the JSON data will be saved with all available posts.
Using the EntrySaved $event variable
Our current code has a problem. The listener is activated not just when the user saves a post, but any entry. This means that when the user saves a page, product, or any other entry we have, it will trigger the event listener. To solve this, we will use the EntrySaved $event variable and its information.
To make it more challenging, let’s say we have a multisite setup in three different languages. We save the posts in separate JSON files based on the locale. So, we don’t want to save all JSON files if we only change one language and not the others. Let’s see how we can do this by further improving our example.
Firstly, we check if the saved entry is a post or not:
if ($event->entry->collection()->handle() == 'posts')
Then, we check to which language that post belongs:
if ($event->entry->site()->name() == 'en') {
To make it more understandable, without any code refactoring, our example will look like this:
namespace App\Listeners;
use Statamic\Facades\Entry;
use Statamic\Events\EntrySaved;
class SavePostsToJson
{
public function handle(EntrySaved $event)
{
if ($event->entry->collection()->handle() == 'posts') {
if ($event->entry->site()->name() == 'en') {
$data = Entry::query()
->where('collection', 'posts')
->where('site', 'en')
->where('published', true)
->get()
->transform(function ($post) {
return [
'title' => $post->title,
'categories' => $post->categories,
'slug' => (string)$post->slug()
];
})
->toArray();
file_put_contents(public_path() . "/search/en/data.json", json_encode($data));
} else {
// some other language
}
}
}
}We’ll refactor the code to follow best practices. Our example includes English and Albanian as alternative languages, with a different default language.
namespace App\Listeners;
use Statamic\Facades\Entry;
use Statamic\Events\EntrySaved;
class SavePostsToJson
{
public function handle(EntrySaved $event)
{
if ($event->entry->collection()->handle() == 'posts') {
if ($event->entry->site()->name() == 'en') {
$this->createEntry('en');
} elseif ($event->entry->site()->name() == 'sq') {
$this->createEntry('sq');
} else {
$this->createEntry('default');
}
}
}
protected function createEntry($lang) {
$data = Entry::query()
->where('collection', 'posts')
->where('site', $lang)
->where('published', true)
->get()
->transform(function ($post) {
return [
'title' => $post->title,
'categories' => $post->categories,
'slug' => (string)$post->slug()
];
})
->toArray();
file_put_contents(public_path() . "/search/{$lang}/data.json", json_encode($data));
}
}Debugging the data
If you want to see what other data the $event variable brings to the table, you can do so by including Laravel’s Log service:
use Illuminate\Support\Facades\Log;
and adding the following code inside the handle function:
Log::debug(print_r($event->entry, true));
You must add it inside print_r() because the log expects a string and not an object. Then simply go to storage/logs/laravel.log and scroll to the end of the file to see what output you got.
Best practices and code refactoring
When creating custom event listeners, it’s important to use best practices and keep your code clean and modular. Refactor your listeners to manage different situations effectively to make your code easier to maintain and read. Whether you work with many languages or various content types, a well-organized listener can significantly improve your Statamic website’s features.
Bring Your Ideas to Life 🚀
Kickstart Your Statamic Project with the #1 Statamic Agency
Are you planning a new Statamic project or thinking about migrating your WordPress site to Statamic? Learn more about our expertise as a renowned Statamic development agency.
Technologies

Stay up-to-date
Be updated with all news, products and tips we share!

