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:
temporarily store the user's details before the save takes place, and log nothing
when saved, get the user's details after the save and compare to the "before" state, and ensure this is added
update the view for the listener
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 them13 // 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): array10 {11 // get previously stored data12 $before = StatamicLogger::getTemporaryData('User-'.$event->user->id);13 14 $data = []; // we need to return an array15 16 // if the roles are DIFFERENT (or NON EXISTANT), add them17 if (!$before || $event->user->roles !== $before['roles']) {18 $data['roles'] = [19 'after' => $event->user->roles,20 'before' => $before['roles'] ?? null21 ];22 }23 24 // return the supplementary data25 return $data;26 }27 28 public function type(): string29 {30 return 'User';31 }32 33 public function view(): string34 {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(): void11 {12 StatamicLogger::subscribe(UserSaving::class, \App\Logger\UserSavingListener::class);13 StatamicLogger::subscribe(UserSaved::class, \App\Logger\UserSavedListener::class);14 }15}