Apparence
Les événements
Quand quelque chose d'important se produit dans le domaine — une commande est passée, un statut change, un compte est créé — le cœur émet un événement. Vous y réagissez par un listener, sans modifier le code qui l'émet.
Le problème
À la validation d'une commande, il faut envoyer un e-mail de confirmation, décrémenter le stock, notifier un ERP… Ces réactions appartiennent à des packages différents, et le cœur ne doit en connaître aucune. L'événement est le point de découplage.
Le principe
Le cœur émet ; plusieurs listeners écoutent, indépendamment.
Les événements de domaine
| Événement | Quand |
|---|---|
OrderPlaced | commande créée et persistée |
OrderStatusChanged | changement de statut de commande |
CartItemAdded / CartItemUpdated / CartItemRemoved | modification du panier |
CartMerged | fusion panier invité → compte |
UserRegistered / UserEmailChanged | cycle de vie du compte |
CurrencyChanged | changement de devise |
ReindexRequested | demande de réindexation produit |
CheckoutStarted / CheckoutStepCompleted / CheckoutCompleted | parcours dans le tunnel de commande |
ProductViewed / CategoryViewed / SearchPerformed | consultation du catalogue |
La liste à jour est dans la référence.
Déclarés par le cœur, émis par le thème
Les événements de parcours (tunnel, consultation) sont déclarés par le framework bien qu'émis par le thème — comme les noms de routes et les slots. Un package de mesure ou de recommandation s'y branche sans dépendre d'un thème particulier.
Empêcher une action : les événements annulables
Les événements ci-dessus constatent (participe passé : CartItemAdded, OrderPlaced). D'autres annoncent une intention avant qu'elle ne soit exécutée (participe présent) : un écouteur peut alors s'y opposer. C'est le seul moyen d'empêcher une action du cœur sans remplacer le service qui la porte.
| Événement | Refus |
|---|---|
CartItemAdding / CartItemUpdating / CartItemRemoving | la méthode du CartService rend false, le panier est inchangé |
OrderPlacing | ActionCancelled est levée avant la transaction — rien n'est écrit |
OrderStatusChanging | ActionCancelled est levée, le statut ne change pas |
php
use Slab\Framework\Core\Cart\Events\CartItemAdding;
Event::listen(CartItemAdding::class, function (CartItemAdding $event): void {
if ($event->product->stock < $event->quantity) {
$event->cancel(__('Stock insuffisant.'));
}
});Le motif du premier écouteur qui s'oppose est conservé : c'est lui qui remonte à l'appelant, et qui porte le message de l'exception Slab\Framework\Core\Event\ActionCancelled (laquelle expose aussi l'événement refusé, via $exception->event).
Pour émettre un tel événement dans votre propre package, faites-lui implémenter CancellableEvent et utilisez le trait Cancellable : sa méthode statique propose(...) construit l'événement, le donne aux écouteurs et le rend — là où dispatch() rend les réponses des écouteurs, seul l'événement porte le veto.
php
$event = MonIntention::propose($contexte);
if ($event->isCancelled()) {
return false; // ou throw new ActionCancelled($event);
}Écouter un événement
Dans un package, l'écoute se déclare explicitement (un provider vendor n'a pas l'auto-découverte des listeners). Le plus simple, au boot() :
php
use Illuminate\Support\Facades\Event;
use Slab\Framework\Core\Order\Events\OrderPlaced;
Event::listen(OrderPlaced::class, function (OrderPlaced $event) {
// $event->order : la commande figée
NotifierErp::dispatch($event->order); // déléguez à un Job pour ne pas bloquer la requête
});Pour une vraie feature, préférez un EventServiceProvider dédié avec un listener dédié (queueable) — c'est ce que fait le cœur pour l'e-mail de statut de commande.
Émettre vos propres événements
Rien ne vous empêche de définir et d'émettre vos événements dans votre package (MonEvent::dispatch(...)) pour que d'autres parties s'y branchent. En revanche, les événements du cœur restent émis par le cœur : vous les écoutez, vous ne les déclenchez pas à sa place.
Voir aussi
- Commande & checkout — le cycle de vie qui émet
OrderPlaced. - Recherche —
ReindexRequestedet l'indexation hors requête.