The Observer Design Pattern in Laravel: A Comprehensive Guide

Moez Missaoui
4 min readJun 25, 2024

--

The Observer Design Pattern is a behavioral design pattern that defines a one-to-many dependency between objects. When one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. This pattern is particularly useful for maintaining consistency between related objects without tightly coupling them.

In Laravel, the Observer pattern is utilized to listen to events fired by Eloquent models. This allows you to handle various model events such as creating, created, updating, updated, deleting, deleted, etc., in a clean and organized manner.

What is the Observer Design Pattern?

The Observer Design Pattern is one of the Gang of Four (GoF) design patterns that aims to promote loose coupling in software design. It consists of two main components:

  1. Subject (Observable): The object that holds the state and sends notifications to observers when its state changes.
  2. Observer: The object that needs to be informed about changes in the subject.

Here’s a basic UML diagram to illustrate the pattern:

+-----------------+        +-----------------+
| Subject | | Observer |
+-----------------+ +-----------------+
| - observers[] | | |
+-----------------+ +-----------------+
| + attach() |<------ | + update() |
| + detach() |------> | |
| + notify() | | |
+-----------------+ +-----------------+

How is the Observer Pattern Used in Laravel?

Laravel provides a clean and straightforward way to implement the Observer pattern with Eloquent models. This allows you to keep your model’s code clean and handle various actions that need to be performed when a model event occurs.

Creating an Observer

To create an observer in Laravel, you can use the make:observer Artisan command:

php artisan make:observer UserObserver --model=User

This command will generate an observer class in the App\Observers directory. The observer will look something like this:

<?php

namespace App\Observers;

use App\Models\User;

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

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

public function updating(User $user)
{
// Logic to execute before a user is updated
}

public function updated(User $user)
{
// Logic to execute after a user is updated
}

public function deleting(User $user)
{
// Logic to execute before a user is deleted
}

public function deleted(User $user)
{
// Logic to execute after a user is deleted
}
}

Registering the Observer

After creating the observer, you need to register it. This is typically done in the boot method of a service provider, such as AppServiceProvider:

<?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);
}

public function register()
{
//
}
}

Using Observers in Laravel

Observers are useful in various scenarios, such as:

  1. Logging Changes: Track changes to a model’s state for auditing purposes.
  2. Sending Notifications: Notify users or other systems about changes to a model.
  3. Updating Related Models: Automatically update related models when a change occurs.
  4. Enforcing Business Rules: Ensure business rules are followed before or after changes to a model.

Example Use Cases

1. Logging User Activity:

Suppose you want to log user activities whenever a user is created or updated. You can handle this in the observer:

<?php

namespace App\Observers;

use App\Models\User;
use App\Models\ActivityLog;

class UserObserver
{
public function created(User $user)
{
ActivityLog::create([
'description' => 'User created: ' . $user->name,
'user_id' => $user->id,
]);
}

public function updated(User $user)
{
ActivityLog::create([
'description' => 'User updated: ' . $user->name,
'user_id' => $user->id,
]);
}
}

2. Sending Welcome Emails:

If you want to send a welcome email to users when they register, you can do this in the created method:

<?php

namespace App\Observers;

use App\Models\User;
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeEmail;

class UserObserver
{
public function created(User $user)
{
Mail::to($user->email)->send(new WelcomeEmail($user));
}
}

3. Auto-Generating Slugs:

To automatically generate slugs for blog posts before they are created or updated:

<?php

namespace App\Observers;

use App\Models\Post;
use Illuminate\Support\Str;

class PostObserver
{
public function creating(Post $post)
{
$post->slug = Str::slug($post->title);
}

public function updating(Post $post)
{
$post->slug = Str::slug($post->title);
}
}

When to Use the Observer Pattern

The Observer pattern is ideal when you need to separate concerns and avoid tight coupling between the model and the actions performed on its events. Use the Observer pattern in Laravel when:

  1. Decoupling Logic: You want to keep your models clean and free from additional responsibilities.
  2. Maintaining Single Responsibility Principle: Each class should have one responsibility, and observers help maintain this principle by handling the event logic separately.
  3. Reusability: Observers can be reused across different models or even in different projects.
  4. Scalability: As your application grows, it becomes easier to manage and scale with observers handling the logic for model events.

Utilities and Benefits of Laravel Observers

  • Cleaner Codebase: Keeps your models focused on their primary responsibilities without the clutter of event handling code.
  • Improved Maintenance: Easier to maintain and update the code as the event handling logic is centralized in observers.
  • Enhanced Reusability: Observers can be applied to multiple models or shared across projects.
  • Better Separation of Concerns: Ensures that the business logic related to model events is separated from the model itself, adhering to SOLID principles.

Conclusion

The Observer design pattern is a powerful tool in Laravel for managing model events in a clean, maintainable, and scalable manner. By using observers, you can decouple your business logic from your models, adhere to best practices, and keep your codebase organized.

Whether you’re logging changes, sending notifications, or updating related models, Laravel observers provide a structured approach to handling these tasks. As your application grows, leveraging the Observer pattern will help you manage complexity and maintain a clean architecture.

Thanks, guys, That’s all for now, If this was helpful for you I’ll really appreciate your feedback and also your claps ! 👏

--

--