Mity Docs Mity Docs for Mity Digital
Logger for Statamic Documentation

Advanced use cases

Logger for Statamic is simple out of the box: but can do some gnarly stuff to give you power and flexibility with your logging.

If you've read this far and have your head around how custom events work, this should all make sense.

Out of the box, logging is fairly standard and simple... but you can take this so much further. If you're doing something cool with Logger for Statamic and want to share its use case, please let us know!

Tracking changes

You can hook in to the "Saving" method of an object - such as a User, Entry, etc - to capture a snapshot of the object before any saving takes place, and then refer back to this after the save has taken place.

Check out the Temporary data docs for full details.

Let's look at tracking changes to a User's roles attribute. The gist of what we need to do is:

  1. temporarily store the user's details before the save takes place, and log nothing

  2. when saved, get the user's details after the save and compare to the "before" state, and ensure this is added

  3. update the view for the listener

  4. subscribe

UserSaving event

Create a new listener for the \Statamic\Events\UserSaving event that extends Logger for Statamic's base User listener, and override the handle method to load the user, and store it for the life of the request:

1namespace App\Logger;
2 
3use MityDigital\StatamicLogger\Facades\StatamicLogger;
4use Statamic\Facades\User;
5 
6class UserSavingListener extends \MityDigital\StatamicLogger\Listeners\User
7{
8 public function handle(mixed $event): void
9 {
10 // by not calling parent::handle($event), we are preventing anything from being logged. Good.
11 
12 // if we have a user, save them
13 // get the event's user (if they exist)
14 $user = User::find($event->user->id);
15 
16 if ($user) {
17 // store the user's current data (for role changes)
18 StatamicLogger::addTemporaryData('User-'.$user->id, $user->toArray());
19 }
20 }
21 
22 public function type(): string {
23 return 'User';
24 }
25}

UserSaved event

Create a new listener for the \Statamic\Events\UserSaved event that extends Logger for Statamic's base User listener, but this time we want to add supplementary data - all of the other behaviour of the base User listener can stay.

We also need to point the listener to our own view.

1<?php
2 
3namespace App\Logger;
4 
5use MityDigital\StatamicLogger\Facades\StatamicLogger;
6 
7class UserSavedListener extends \MityDigital\StatamicLogger\Listeners\User
8{
9 protected function supplement($event): array
10 {
11 // get previously stored data
12 $before = StatamicLogger::getTemporaryData('User-'.$event->user->id);
13 
14 $data = []; // we need to return an array
15 
16 // if the roles are DIFFERENT (or NON EXISTANT), add them
17 if (!$before || $event->user->roles !== $before['roles']) {
18 $data['roles'] = [
19 'after' => $event->user->roles,
20 'before' => $before['roles'] ?? null
21 ];
22 }
23 
24 // return the supplementary data
25 return $data;
26 }
27 
28 public function type(): string
29 {
30 return 'User';
31 }
32 
33 public function view(): string
34 {
35 return 'logger.user';
36 }
37}

Update the view

In our site's resources/views/logger folder, we need to add user.blade.php.

This is the same as the built-in view, but we now are checking if we have a roles property - this is what we added in our UserSavedListener. If we have that, we now output the before and after details of the change.

1<div>{{ $data->name }} {{ strtolower($handler->action($event)) }}</div>
2<div class="text-xs text-gray-500">ID: {{ $data->id }}</div>
3@if (property_exists($data, 'roles'))
4 <div class="text-xs mt-1">
5 <div><strong>Roles changed:</strong></div>
6 <ul class="ml-4">
7 <li>Was: {{ is_array($data->roles->before) ? implode(', ', $data->roles->before) : '-' }}</li>
8 <li>Now: {{ is_array($data->roles->after) ? implode(', ', $data->roles->after) : '-' }}</li>
9 </ul>
10 </div>
11@endif

Subscribe

And finally, we need to tell Logger for Statamic about our new listeners:

1namespace App\Providers;
2 
3use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
4use MityDigital\StatamicLogger\Facades\StatamicLogger;
5use Statamic\Events\UserSaved;
6use Statamic\Events\UserSaving;
7 
8class EventServiceProvider extends ServiceProvider
9{
10 public function boot(): void
11 {
12 StatamicLogger::subscribe(UserSaving::class, \App\Logger\UserSavingListener::class);
13 StatamicLogger::subscribe(UserSaved::class, \App\Logger\UserSavedListener::class);
14 }
15}