Introduction
Laravel's Eloquent OM is the rock-solid implementation of Active Record. It has many features includes Observers, Laravel implements Observer Pattern to fire some events, which can be listened to hook into, when various actions are performed on a model.
Requisite
You must have the least basic knowledge in laravel and how to generate models and knowledge in MVC Pattern and PHP in general.
Laravel Model Events
If you worked before in a medium to large scale project with laravel, you may notice you need to fire an event in some situation to keep your project nice and clean and easy to maintain. One of the Events in laravel is Model Events, that let you do some actions after the model saved, saving ...
Let's take an example, imagine You have Article
model, and you want to set a slug
automatically to saving the article. Instead of setting the slug when the articles got saved:
1Article::create([2 'title' => $name,3 'slug' => Str::slug($name),4]);
You can do the following:
1use Illuminate\Support\Str; 2 3class Article extends Model 4{ 5 ... 6 7 protected static function boot() 8 { 9 parent::boot();10 11 static::saving( function ($model) {12 $model->slug = Str::slug($model->title);13 })14 }15}
This method is very straight forward, because if you have a multiple models requires a slug, you can a single Trait and use this method into it and implement the trait in every model requires a slug to be filled. I hope you got the idea.
The saving
event is one of the provided events that Eloquent provides:
- retrieved: after a record has been retrieved.
- creating: before a record has been created.
- created: after a record has been created.
- updating: before a record is updated.
- updated: after a record has been updated.
- saving: before a record is saved (either created or updated).
- saved: after a record has been saved (either created or updated).
- deleting: before a record is deleted or soft-deleted.
- restoring: before a soft-deleted record is going to be restored
- restored: after a soft-deleted record has been restored.
You can use any of the methods listed above like we did before with saving
Laravel Model Observers
If you are planing to use more than one of the listed events above (depend on of your project), it is not a good idea to place all of them in your model. Laravel solved you issue and provided you with observer
command to generate class contain all the available events, you can generate observer class like so:
1php artisan make:observer ArticleObserver --model=Article
As the command tell, you are generating an observer class for the article model, and you can change it to the needed model.
The generated Observer leaves in app/Observers
folder and contain the code below:
1namespace App\Observers; 2 3use App\Models\Post; 4 5class PostObserver 6{ 7 /** 8 * Handle the article "created" event. 9 *10 * @param \App\Models\Article $article11 * @return void12 */13 public function created(Article $article)14 {15 //16 }17 18 /**19 * Handle the article "updated" event.20 *21 * @param \App\Models\Article $article22 * @return void23 */24 public function updated(Article $article)25 {26 //27 }28 29 /**30 * Handle the article "deleted" event.31 *32 * @param \App\Models\Article $article33 * @return void34 */35 public function deleted(Article $article)36 {37 //38 }39 40 /**41 * Handle the article "restored" event.42 *43 * @param \App\Models\Article $article44 * @return void45 */46 public function restored(Article $article)47 {48 //49 }50 51 /**52 * Handle the article "force deleted" event.53 *54 * @param \App\Models\Article $article55 * @return void56 */57 public function forceDeleted(Article $article)58 {59 //60 }61}
After the observer class generated successfully you need to register it inside AppServiceProvider
in app/Providers/AppServiceProvider
folder inside the boot()
method
1...2public function boot()3{4 Article::observe(ArticleObserver::class);5}6...
Now we have successfully added a model observer to Article
model, and you are good to go with your application.
Real Life Example
Some of you see the explanation above and other not (including me) so, we will build a small application to show you how to use them properly.
Now, we have a User
model (came by default in laravel) and Article
model generated before, normally the user have many articles and let's assume we deleted the user from our records, well. There're many scenarios on how to deal with the articles created by the deleted user but, let's delete his/her article as well.
You may want to define the relationship first:
1class User extends Model2{3 public function articles()4 {5 return $this->hasMany(Article::class);6 }7}
Let's generate a new User
Observer
1php artisan make:observer UserObserver --model=User
After you registered the UserObserver
inside AppServiceProvider
as we do in ArticleObserver
above, let's open it and make
some modifications
1class UserObserver 2{ 3 /** 4 * Handle the user "deleting" event. 5 * 6 * @param \App\User $user 7 * @return void 8 */ 9 public function deleting(User $user)10 {11 $user->articles()->delete();12 }13}
Note: You are not forced to keep the unneeded methods, and you may only keep the one who you are truly need it
So, All what we are doing here, after the user get delete the articles belongs to him deleted as well. That's all, Coll, isn't it?
Tips
Everything's in this world has limitation and the Model Observers among them. You should keep in mind while you are using the model observers the following:
- When you use saved or saving hooks (events), you should never call the model's save method
- If you are using
saved
hook and want to call the save method, then you should probably use thesaving
hook as well. - if your logic need to call model's save method. Then rethink your logic or avoid using observers.
If you're not familiar with save
method here is a small definition from Laravel Documentation:
Eloquent provides convenient methods for adding new models to relationships. For example, perhaps you need to add a new comment to a post. Instead of manually setting the post_id attribute on the Comment model you may insert the comment using the relationship's save method:
1use App\Models\Comment;2use App\Models\Post;3 4$comment = new Comment(['message' => 'A new comment.']);5 6$post = Post::find(1);7 8$post->comments()->save($comment);
Conclusion
Laravel Model Observers are a very powerful and useful features and helps to keep your code maintainable and easy to understand.
You should keep in mind the limitation above in the Tips section to avoid any problems with your code base.
That's it for today and if you have any questions about the Observers, you can ask me at any time.
If you enjoy with my articles you can follow me at Twitter for more Tips and Tricks about laravel.