Sling Academy
Home/PHP/How to define and use observers in Eloquent

How to define and use observers in Eloquent

Last updated: January 16, 2024

Introduction

When working with Eloquent in Laravel, you often need to execute certain actions during various stages of the model’s lifecycle, such as creating, updating, or deleting records. The Eloquent Observer class provides a convenient method to hook into these lifecycle events, allowing you to keep your code clean and maintainable. In this tutorial, we’ll explore how to define and use observers in Eloquent through a series of examples, ranging from basic to advanced.

Eloquent Observer: The Basics

An Eloquent Observer is a class where you can define methods to listen to various Eloquent events. These events allow you to perform actions before or after operations such as creating, updating, saving, deleting, restoring, and more on a model. By harnessing these methods, you can refactor repetitive code out of your models and ensure a separation of concerns within your application’s architecture.

Defining an Eloquent Observer

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    public function creating(User $user)
    {
        // Logic before a user record is created
    }

    public function created(User $user)
    {
        // Logic after a user record is created
    }

    // Other model events...
}

Registering an Eloquent Observer

To register an observer, you’ll typically do so within the boot method of one of your service providers, usually the AppServiceProvider. You’ll use the observe method on the model to attach the observer class.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Models\User;
use App\Observers\UserObserver;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        User::observe(UserObserver::class);
    }
}

Observer Methods

Here are the methods you can define within an observer:

  • retrieved
  • creating
  • created
  • updating
  • updated
  • saving
  • saved
  • deleting
  • deleted
  • restoring
  • restored

Example: Automatic Timestamps

This example demonstrates how to automatically set a timestamp on a custom field whenever a record is saved or updated.

<?php

namespace App\Observers;

use App\Models\Post;

class PostObserver
{
    public function saving(Post $post)
    {
        $post->last_action_at = now();
    }
}

In your AppServiceProvider, you would attach this observer to the Post model:

<?php

namespace App\Providers;

use App\Models\Post;
use App\Observers\PostObserver;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Post::observe(PostObserver::class);
    }
}

Advanced Observer Usage

Dependency Injection

Observers can also receive dependencies through dependency injection. For instance, if you need to send an email after a user registers, you could inject a mailer service into your observer.

<?php

namespace App\Observers;

use App\Models\User;
use Illuminate\Mail\Mailer;

class UserObserver
{
    protected $mailer;

    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    public function created(User $user)
    {
        // Send email...
    }
}

Using Observers with Queues

If you need to perform time-consuming tasks, like sending an email, you should queue those tasks to make your application more responsive. Here’s how you could queue a mail job within an observer method.

<?php

namespace App\Observers;

use App\Jobs\SendWelcomeEmail;
use App\Models\User;

class UserObserver
{
    public function created(User $user)
    {
        dispatch(new SendWelcomeEmail($user));
    }
}

Caveats and Considerations

While observers can improve code maintainability, they also introduce a level of indirection which can make code harder to trace. Be sure also to consider the implications of using observers, such as the potential for recursion when an observer triggers another event unintentionally.

Conclusion

Observers in Eloquent present an elegant way of handling model lifecycle events in a Laravel application. They are easy to implement, and when used appropriately, can lead to more maintainable and extensible code. As with any design pattern, it’s essential to use them judiciously to fully reap the benefits.

Next Article: How to Temporarily Disable Events in Eloquent

Previous Article: How to register and use closures in Eloquent

Series: Laravel & Eloquent Tutorials

PHP

You May Also Like

  • Pandas DataFrame.value_counts() method: Explained with examples
  • Constructor Property Promotion in PHP: Tutorial & Examples
  • Understanding mixed types in PHP (5 examples)
  • Union Types in PHP: A practical guide (5 examples)
  • PHP: How to implement type checking in a function (PHP 8+)
  • Symfony + Doctrine: Implementing cursor-based pagination
  • Laravel + Eloquent: How to Group Data by Multiple Columns
  • PHP: How to convert CSV data to HTML tables
  • Using ‘never’ return type in PHP (PHP 8.1+)
  • Nullable (Optional) Types in PHP: A practical guide (5 examples)
  • Explore Attributes (Annotations) in Modern PHP (5 examples)
  • An introduction to WeakMap in PHP (6 examples)
  • Type Declarations for Class Properties in PHP (5 examples)
  • Static Return Type in PHP: Explained with examples
  • PHP: Using DocBlock comments to annotate variables
  • PHP: How to ping a server/website and get the response time
  • PHP: 3 Ways to Get City/Country from IP Address
  • PHP: How to find the mode(s) of an array (4 examples)
  • PHP: Calculate standard deviation & variance of an array