Observateurs dans Laravel

Lors du développement sur un projet Web, vous pourriez avoir besoin que quelque chose se produise lorsqu’une table de la base de données est modifiée. Par exemple, vous pourriez vouloir envoyer une notification de confirmation à un utilisateur chaque fois qu’un enregistrement est créé. Ou vous pourriez vouloir créer un enregistrement dans une table de journal chaque fois qu’un enregistrement est mis à jour ou supprimé. Ou vous pourriez vouloir assainir vos données avant qu’elles ne soient envoyées à la base de données et supprimer toutes les balises html ou script.

Bien que vous puissiez le faire dans vos méthodes de contrôleur, il y a de fortes chances que vous manipuliez une table à plusieurs endroits, et que vous devriez maintenir aussi ce code à plusieurs endroits. Une façon plus efficace de procéder est de placer le code dans les événements intégrés de Laravel.

Événements du modèle

Laravel comprend un certain nombre d’événements qui se déclenchent pendant la durée de vie d’un modèle. Ces événements correspondent à différentes actions effectuées sur une table de base de données. Ces événements comprennent la création d’un enregistrement : la mise à jour d’un enregistrement, l’enregistrement (qui est déclenché en tant que partie de la création ou de la mise à jour) et la suppression.

Il y a en fait deux événements qui se déclenchent pour chacun de ces événements ; un événement se produit avant que l’action ne se produise, et l’autre se produit après qu’elle se soit produite. Par exemple, l’événement de création se déclenche avant que l’enregistrement ne soit créé dans la base de données, tandis que l’événement de création se déclenche une fois que l’enregistrement a été créé. La liste complète ressemble à ceci :

  • Création/Créé
  • Mise à jour/Updated
  • Sauvegarde/Sauvegardé
  • Suppression/supprimé
  • Forcer la suppression/Forcer la suppression
  • Restaurer/Restaurer

Remarque : l’exécution d’une mise à jour ou d’une suppression de masse (par exemple – User::where(‘active’, ‘=’, 0)->delete();) ne déclenchera pas d’événement, car les modèles ne sont pas réellement récupérés dans ces cas-là. Dans ce cas, vous pourriez vouloir récupérer les enregistrements et les parcourir en boucle pour effectuer la mise à jour/suppression.

Il existe plusieurs façons de se connecter à ces événements ; ci-dessous, nous examinerons deux des plus courantes : les fermetures (closures) et les observateurs (observers).

Fermetures

Les modèles Eloquent ont une méthode statique définie pour chaque événement (création, mise à jour, suppression etc), qui peut être utilisée pour enregistrer des fermetures pour chaque événement. Ces fermetures sont définies dans la méthode booted du modèle.

Nous allons prendre l’exemple d’une simple table utilisée pour stocker les rendez-vous. Lorsqu’un rendez-vous est créé, nous voulons envoyer une AppointmentNotification (qui, nous le supposons, a déjà été créée dans le système) à l’utilisateur associé au rendez-vous.

use App\Notifications\AppointmentNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use App\Notifications\AppointmentNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Appointment extends Model
{
    use HasFactory;

    // ***********************************
    #region Booted
    // ***********************************
    protected static function booted() {
        parent::booted();

        static::created(function (Appointment $appointment) {
            $appointment->user()->notify(new AppointmentNotification($appointment));
        });
    }
    #endregion

    // ***********************************
    #region Relationships
    // ***********************************
    public function user() {
        return $this->belongsTo(User::class);
    }
    #endregion
}

Dans l’exemple ci-dessus, vous remarquerez que nous avons ajouté cette ligne à la méthode booted de la classe Appointment :

        $appointment->user()->notify(new AppointmentNotification($appointment));

Cela indique à Laravel qu’après la création d’un rendez-vous, nous voulons récupérer l’utilisateur associé au rendez-vous, puis envoyer une notification à cet utilisateur.

Si vous désirez exécuter le code en arrière-plan, vous pouvez enregistrer l’événement comme pouvant être mis en file d’attente. Cela exécutera l’écouteur d’événement dans la file d’attente de l’application :

use function Illuminate\Events\queueable;

//...

static::created(queueable(function (Appointment $appointment) {
    // ...
}));

Observateurs

Si vous avez besoin d’écouter plusieurs événements sur un modèle, vous pouvez les regrouper à l’aide d’un observateur. Un observateur est un objet qui possède des méthodes pour chacun des événements du modèle, chacune d’entre elles recevant le modèle affecté en tant qu’argument. Les observateurs sont créés à l’aide d’une commande Artisan :

php artisan make:observer AppointmentObserver –model=User

Cette commande crée un nouvel observateur dans le répertoire app/Observers. Lors de sa première création, l’observateur ressemblera à quelque chose comme ceci :

use App\Models\Appointment;

class AppointmentObserver
{
    /**
     * Handle the Appointment "created" event.
     */
    public function created(Appointment $appointment): void
    {
        // ...
    }

    /**
    * Handle the Appointment "updated" event.
    */
    public function updated(Appointment $appointment): void
    {
        // ...
    }
    
    /**
    * Handle the Appointment "deleted" event.
    */
    public function deleted(Appointment $appointment): void
    {
        // ...
    }
}

Nous pouvons maintenant ajouter notre code pour envoyer la notification de rendez-vous à la méthode created :

use App\Notifications\AppointmentNotification;
...

public function created(Appointment $appointment): void
{
    $appointment->user()->notify(new AppointmentNotification($appointment));
}

Une fois l’observateur créé, vous devrez l’enregistrer dans la méthode boot de la classe App\Providers\EventServiceProvider pour commencer à écouter les événements.

use App\Models\Appointment;
use App\Observers\AppointmentObserver;

/**

Register any events for your application.
*/
public function boot(): void
{
 Appointment::observe(AppointmentObserver::class);
}

Vous pouvez également dresser la liste des observateurs dans la propriété observers de la classe App\Providers\EventServiceProvider.

use App\Models\Appointment;
use App\Observers\AppointmentObserver;

 /**

The model observers for your application.

@var array
*/
protected $observers = [
 Appointment::class => [AppointmentObserver::class],
];

Mise en sourdine des événements

Il peut arriver que vous ayez besoin d’exécuter une commande sur le modèle sans déclencher d’événements ; il y a plusieurs façons de le faire. La méthode withoutEvents accepte une fermeture comme argument ; tout code exécuté à l’intérieur de cette fermeture ne déclenchera pas d’événement.

use App\Models\Appointment

$appointment = Appointment::withoutEvents(function() {
    $appointment = Appointment::findOrFail(1)->update['cancelled=>true]);
   ....
    return $appoitnment
});

L’utilisation de withoutEvents est pratique si vous modifiez plusieurs enregistrements ou si vous effectuez plusieurs actions sur un modèle. Si vous devez exécuter une seule action sur un modèle, vous pouvez utiliser des méthodes comme saveQuietly, deleteQuietly, forceDeleteQuietly et restoreQuietly.

$appointment = Appointment::findOrFail(1);
$appointment->cancelled = true;
$appointment->saveQuietly();

Conclusion

Nous espérons que cela a permis de clarifier le rôle des observateurs dans Laravel, et que vous avez désormais une meilleure idée de quand et comment les utiliser. Si vous avez un projet Laravel en tête, nous serions ravis de vous aider. Envoyez-nous un message et nous prendrons contact avec vous.