Comprehensive Guide to Using Observers in Laravel
Published: 2024-05-25 16:42:45



## Introduction

Laravel Observers are a powerful feature that allows you to hook into the lifecycle events of your Eloquent models. By using observers, you can listen for various events that are fired by the model, such as when a model is created, updated, or deleted, and then execute specific logic in response to those events. This helps in keeping your code clean and maintaining the single responsibility principle.

## Lifecycle Events

Observers can listen to the following model events:

- `retrieved`
- `creating`
- `created`
- `updating`
- `updated`
- `saving`
- `saved`
- `deleting`
- `deleted`
- `restoring`
- `restored`

In this article, I will show a quick use case of sending user authentication credentials to a new user upon profiling. We will create a user model observer that sends an email to the new user when admin creates his profile on the system.

## Creating an Observer

To create an observer, you can use the `make:observer` Artisan command. For example, to create an observer for the `User` model, you would run:

```sh
php artisan make:observer UserObserver --model=User
```

This command will generate a new observer class in the `app/Observers` directory.

## Registering an Observer

To register the observer, you need to add it to the `boot` method of one of your service providers, typically the `AppServiceProvider`. For example:

```php
use App\Models\User;
use App\Observers\UserObserver;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    User::observe(UserObserver::class);
}
```

## Creating the UserCredentials notification class

Create a notification class to send the email if it doesn't already exist:

```sh
php artisan make:notification UserCredentials
```

Update the UserCredentials notification:

```php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class UserCredentials extends Notification
{
    use Queueable;

    protected $username;
    protected $password;

    /**
     * Create a new notification instance.
     *
     * @param string $username
     * @param string $password
     * @return void
     */
    public function __construct($username, $password)
    {
        $this->username = $username;
        $this->password = $password;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param mixed $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param mixed $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->greeting('Hello!')
                    ->line('Your account has been created.')
                    ->line('Username: ' . $this->username)
                    ->line('Password: ' . $this->password)
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param mixed $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

```

## Sample Observer

Here's an example of a `UserObserver` that listens for the `created` events:

```php
namespace App\Observers;

use App\Models\User;
use App\Notifications\UserCredentials;
use Illuminate\Support\Facades\Log;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        $plainPassword = $user->password;
        $user->notify(new UserCredentials($user->email, $plainPassword));

     /** Ensure the password is hashed if the create method 
      *  had saved plain text from the controller
      */

        $user->password = Hash::make($plainPassword);

    }
    // Other events can be handled similarly...
}
```

## Using the Observer

Once the observer is registered, it will automatically listen for the specified events on the model. For example, whenever a `User` model is created, the corresponding methods in the `UserObserver` will be executed, thereby sending the login credential to the created user.

## Benefits of Using Observers

1. **Separation of Concerns**: Observers help in keeping the model and business logic separate. This makes the codebase cleaner and more maintainable.

2. **Code Reusability**: By using observers, you can reuse the same logic across multiple parts of your application without duplicating code.

3. **Centralized Logic**: Observers allow you to centralize event-based logic in one place, making it easier to manage and update.

4. **Enhanced Readability**: With observers, your models are free from additional responsibilities, making them easier to read and understand.

5. **Easy Testing**: Observers can be tested independently of the models, which simplifies the testing process.

## Conclusion

Laravel Observers provide a structured and efficient way to handle model events. By leveraging observers, you can keep your codebase clean, maintainable, and adhere to best practices like the single responsibility principle. They are a valuable tool in any Laravel developer's arsenal, promoting better organization and modularization of code.