Skip to main content
Category:

Laravel Model Events

If you have used Laravel for a medium to large scale project, you might have encountered a situation where you want to perform some action while your Eloquent model is processing. Laravel’s Eloquent provide a convenient way to add your own action while the model is completing or has completed some action.

For example, if you have Post model and you want to set post slug automatically when a post is created. You can listen to the saving event and set the post slug like below:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = ['title', 'slug', 'content'];

    protected static function boot()
    {
        parent::boot();
        static::saving(function ($model) {
            $model->slug = str_slug($model->title);
        });
    }
}

 

Eloquent provides a handful of events to monitor the model state which are:

  • 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.
  • deleted : after a record has been deleted or soft-deleted.
  • restoring : before a soft-deleted record is going to be restored.
  • restored : after a soft-deleted record has been restored.

 

Laravel Model Observers

Imagine your application is growing, and you have to listen to most of the above events in your model, listening to the events within the model will make your model very big and messy of course.

Using model observers, you can group all your events into a single class. All method names in the observer class will reflect on the event you are listening to. You can create a model observer class using below artisan command.

php artisan make:observer PostObserver --model=Post

Above command will create a new class located in the app/Observers folder. Your newly created observer class will look like below:

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "created" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function created(Post $post)
    {
        //
    }

    /**
     * Handle the post "updated" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function updated(Post $post)
    {
        //
    }

    /**
     * Handle the post "deleted" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function deleted(Post $post)
    {
        //
    }

    /**
     * Handle the post "restored" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function restored(Post $post)
    {
        //
    }

    /**
     * Handle the post "force deleted" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function forceDeleted(Post $post)
    {
        //
    }
}

 

 

To register an observer, you need to call the observe method on the model you wish to observe. You may register observers in the boot method of your application's App\Providers\EventServiceProvider service provider:

use App\Post;
use App\Observers\PostObserver;
use Illuminate\Support\ServiceProvider;

/**
 * Register any events for your application.
 *
 * @return void
 */
public function boot()
{
    Post::observe(PostObserver::class);
}

 

In our PostObserver class, Laravel created some function by default like created, updated and others. We will delete all of them and add a saving hook by telling to create a post slug from post title before the post is saved.

Replace your observer class with below.

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "saving" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function saving(Post $post)
    {
        $post->slug = str_slug($post->title);
    }
}

Now we have successfully added a model observer to observe our Post model, whenever you create a new post, it’s slug will be automatically created before saving the post.

 

Practicle Example

For example, our Post model has associated comments. What will happen if I delete a post, will that delete the comments as well?

Of Course Not

Obviously, we don’t want to delete the post comments manually in our code base where we are deleting the post. We can use the deleting hook to do this for us.

You might will have a HasMany relationship to the Comment model and you model will look like below.

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = ['title', 'slug', 'content'];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

 

Now we can add a deleting hook in our PostObserver class like below and delete the attached comments in it.

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "saving" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function saving(Post $post)
    {
        $post->slug = str_slug($post->title);
    }

    /**
     * Handle the post "deleting" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function deleting(Post $post)
    {
        $post->comments()->delete();
    }
}

 

Now every time, you delete a post, all comments associated with that post will get deleted.

Limitations

There are some limitations attached to Model Observer which you should keep in mind while using the model observers.

  • When you use saved or saving hooks, 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 the saving hook.
  • If your logic need to call model’s save method, then rethink your logic or avoid using observers.

 

Riadh Rahmi

Senior Web Developer PHP/Drupal & Laravel

I am a senior web developer, I have experience in planning and developing large scale dynamic web solutions especially in Drupal & Laravel.

Web Posts

Search

Page Facebook