Laravel Observers - The Cleanest Way to Handle Model Events

As your Laravel app grows, repetitive tasks can clutter your controllers and models. Now imagine this: when a customer places an order—...

Karan Datwani
Karan Datwani
Share:

As your Laravel app grows, repetitive tasks can clutter your controllers and models.

Now imagine this: when a customer places an order—whether from your mobile app, website, or an external API— application should reduce the stock, send a confirmation email, and log the action automatically, no matter where the order came from.

Observers let you automate model event logic in one centralized place—keeping your code clean, consistent, and scalable across your entire application. In this article, I'll discuss:

  • What are Laravel Observers and why use them?
  • How To Create Observer?
  • Observers Vs Events & Listeners

What are Laravel Observers?

Laravel Observers are classes that listen to model events and automatically trigger logic - either in the response... or in the background! They help separate event-related logic out of your models and controllers.

For example, in an e-commerce app, when a customer places an order, an observer can:

  • Reduce the product inventory when the order is confirmed.
  • Send a confirmation email with the invoice.

By using an Observer, it's easy to avoid code duplication and ensure that these tasks are handled automatically.

Why Use Observers?

  1. Clean, Maintainable Code: Observers help keep models and controllers free of repetitive tasks.
  2. Easier Debugging: All logic related to a model’s lifecycle is centralized, making it easier to trace and debug.
  3. Improved Performance: Observers can run tasks in the background using queues. This helps the app respond faster for a smoother user experience.

Lifecycle Hooks in Observers

Laravel supports multiple model event hooks:

Hook Trigger
retrieved After a model is fetched
creating Before a model is created
created After a model is created
updating Before a model is updated
updated After a model is updated
saving Before a model is saved
saved After a model is saved
deleting Before a model is deleted
deleted After a model is deleted
restoring Before a soft-deleted model is restored
restored After a model is restored

How To Create Observer?

Let's take the same example of an e-commerce application, where on order confirmation, stock is deducted and a confirmation mail is sent with the invoice to the customer.

1. Create the observer

Let's create the observer file which will observe when an order is confirmed and execute the specific set of actions.

php artisan make:observer OrderObserver --model=Order

2. Implement the Observer

Now, let's define the core logic of the Observer, which is easy to understand.

class OrderObserver {

    // Triggered when an order is created
    public function created(Order $order) {
        // Thankyou mail to customer
        Mail::to($order->user->email)->send(new OrderThanks($order));

        // Order notification to admin
        Notification::route('slack', env('SLACK_WEBHOOK'))->notify(new OrderNotification($order));
    }

    // Triggered when an order status is updated
    public function updated(Order $order) {
        if ($order->status === 'confirmed' && $order->getOriginal('status') !== 'confirmed') {
            // Deduct order item's stock
            foreach ($order->products as $product) {
                $product->decrement('stock', $product->pivot->quantity);
            }        

            // Send confirmation email
            Mail::to($order->user->email)->send(new OrderConfirmation($order));

            // Log order confirmation
            Log::info("Order confirmed", ['order_id' => $order->id, 'user_id' => $order->user_id]);
        }

        if ($order->status === 'shipped' && $order->getOriginal('status') !== 'shipped') {
            // Send shipment update
            Mail::to($order->user->email)->send(new OrderShipment($order));
        }
    }
    
}

Note: Never use request() inside observers — use model relationships or attributes to get data.

3. Register the Observer

Now, the next step is to register the observer inside AppServiceProvider.php.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Models\Order;
use App\Observers\OrderObserver;

class AppServiceProvider extends ServiceProvider {    
    
    public function boot(): void {
        Order::observe(OrderObserver::class);
    }
}

Now it will start listening for events on the Order model and handle the predefined actions. Forgetting to register the observer in AppServiceProvider means it won’t work.

Example Usage

// Create new order
$order = Order::create([
    'user_id' => 1,
    'status' => 'pending',
    'total_amount' => 100
]);
$order->products()->attach([
    1 => ['quantity' => 2],
    3 => ['quantity' => 1]
]);

// Update order status to confirmed (triggers stock deduction and confirmation email)
$order->update(['status' => 'confirmed']);

// Update order status to shipped (triggers shipment email)
$order->update(['status' => 'shipped']);

When the order status changes to confirmed, OrderObserver listens for the update event on the Order model. It then deducts stock, sends a confirmation email, and logs the event. Similarly, when the status changes to shipped, it sends a shipment notification.

Using Queued Observers

For time-consuming tasks like sending emails, implement ShouldQueue on your observer to run these tasks in the background.

use Illuminate\Contracts\Queue\ShouldQueue;

class OrderObserver implements ShouldQueue {
    // Now runs in the background automatically
}

Make sure to configure your queue workers to process queued jobs properly.

Observers vs Events & Listeners

Feature Observers Events & Listeners
Scope Model-specific App-wide
Decoupling Tight Loose
Use Case CRUD-related automation Complex workflows, multiple handlers
Queuing Can be queued Can be queued

Use Observers for simple, model-tied logic. Use Events/Listeners when the action spans multiple parts of the system.

Final Word

If you have been handling model related events manually until now - both in the front and and in the backoffice, I recommend you try this way of doing things.💻🙍‍♂️

Laravel Observers are a great way to keep your models clean, automate common tasks, and improve application structure. Whether you’re building a small app or scaling up to event-driven architecture, they’re a simple and powerful tool to have in your toolbox.

Take initiative, implement Observers — and enjoy writing smarter, cleaner code.

Happy coding!

Want to receive more articles like this?

Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.

Reactions & Comments

What do you think about this?

Latest Articles

Wondering what our community has been up to?