Quite often you will need to perform actions when a model is created or changed.
Say you have a Posts model, you might want to send notifications of the new post to subscribers, or you might want to notify an admin every time a post is edited.
Whatever the situation, it’s automatic for us to put these actions in the controller that handles this creation or edit - after all, the controller is responsible for that action right?
That’s where observers can step in, to clean up your controller code and ensure these actions are performed however a model is updated.
What is an Observer?
Observers are classes that contain methods that are triggered when a models state changes. Under the hood, Laravel triggers events that observers can listen to.
Observers can perform actions on create, update, delete, restored and forceDelete.
When do Restored and forceDelete trigger?
These events are triggered on models that are using Soft Deletes, when either restoring or force deleting. Read more about soft deleting.
The idea is that whenever one of these actions is performed on a model - regardless of where or how - your actions are performed.
Think about this example:
You have a Users model, and in your application users can update their own information. Admins can also update a user's information. These two updates will typically be performed by different controllers.
Add to this equation an artisan command that updates users in bulk somehow, or there may be a scheduled task that updates users information.
In all of these situations, there could be additional actions to perform other than the update itself - such as notifying the user of the change, or logging the change for admin purposes.
It doesn’t make sense to have this duplication of code - if you wanted to change how these actions or fix a bug you’d have to do it 4 times.
That’s the perfect use case for an observer. It will listen for the change and perform actions every time.
Creating an Observer
Now you’re saying “less waffle Stef, how do I do this?”
Well, here we go. There’s an artisan command to generate an Observer:
php artisan make:observer UserObserver --model=User
This will create the class in an Observers directory, and if you open up that new class you’ll see the following boilerplate:
<?php
namespace App\Observers;
use App\Models\User;
class UserObserver
{
public function created(User $user)
{
//
}
public function updated(User $user)
{
//
}
public function deleted(User $user)
{
//
}
public function restored(User $user)
{
//
}
public function forceDeleted(User $user)
{
//
}
}
As you can see, there’s a method for create, update, delete, restored and forceDelete.
These methods accept the model as a parameter.
And quite simply, you can go ahead and perform whatever action you need to in these methods!
Here’s an example where we send a notification on update:
use App\Notifications\UserUpdated;
...
public function updated(User $user)
{
$user->notify(new UserUpdated($user));
}
Simple right?
Registering Observers
There’s one final thing to do to get Laravel to use our Observer - we need to register it.
To do this we add the following to the boot
method of our App\Providers\EventServiceProvider
service provider:
use App\Models\User;
use App\Observers\UserObserver;
...
public function boot()
{
User::observe(UserObserver::class);
}
Now, Laravel with use our Observer methods.
Skipping Observers
Observers are great, but there might be situations where you want to not have them run.
It could be that the scheduled task we mentioned before is just doing some clean up so the user doesn’t need to be notified every time.
In that case, you can use the saveQuietly method instead, for example:
$user->saveQuietly();
Further Reading
Of course, Laravel's documentation includes a section detailing how Observers can be used. Be sure to head over there to read more about them.
Observers: Done
And there you have it, Observers give you a nice clean way to react to model changes and perform actions in one place rather than duplicating code.
If you have any questions about Observers or Laravel in general, or any feedback about this article, drop me a comment below - I’m always happy to chat about code!
Until next time, happy coding.
Top comments (0)