Repenser le modèle d'observateur de Laravel

DEV - 11/02
Laissez-moi vous parler de l'observateur qui m'a brisé. Cela a commencé innocemment. Un client avait besoin d'un email...

Laissez-moi vous parler de l'observateur qui m'a brisé.

Cela a commencé innocemment. Un client avait besoin d'un e-mail envoyé lorsque le statut du compte d'un utilisateur changeait. Facile - j'utiliserai un observateur :

class UserObserver { fonction publique mise à jour (Utilisateur $user) { if ($user->wasChanged('status')) { Mail::to($user)->send(new AccountStatusChanged($user)); } } }
Entrer en mode plein écran Quitter le mode plein écran

Faire le ménage. Simple. Meilleures pratiques Laravel.

Ensuite, les exigences ont continué à affluer.

L'observateur qui a mangé ma base de code

« Pouvons-nous également synchroniser les changements de statut avec Salesforce ? »

fonction publique mise à jour (Utilisateur $user) { if ($user->wasChanged('status')) { Mail::to($user)->send(new AccountStatusChanged($user)); // Nouvelle application d'exigence (SalesforceClient::class)->updateContact($user->salesforce_id, [ 'status' => $user->status, ]); } }
Entrer en mode plein écran Quitter le mode plein écran

"Nous devons mettre à jour l'abonnement Stripe de l'utilisateur lorsque son forfait change."

fonction publique mise à jour (Utilisateur $user) { if ($user->wasChanged('status')) { Mail::to($user)->send(new AccountStatusChanged($user)); app(SalesforceClient::class)->updateContact($user->salesforce_id, [ 'status' => $user->status, ]); } // Une autre exigence if ($user->wasChanged('plan')) { app(StripeClient::class)->updateSubscription( $user->stripe_subscription_id, ['price' => $user->plan->stripe_price_id] ); } }
Entrer en mode plein écran Quitter le mode plein écran

"L'équipe marketing doit savoir quand les e-mails changent pour sa liste de diffusion."

"Le service juridique veut un journal d'audit de toutes les modifications de profil."

« Pouvons-nous avertir le responsable de compte lorsqu'un client de grande valeur modifie quelque chose ? »

Six mois plus tard :

class UserObserver { fonction publique __construct( private SalesforceClient $salesforce, private StripeClient $stripe, private MailingListService $mailingList, private AuditLogger $auditLogger, private SlackNotifier $slack, private AnalyticsService $analytics, ) {} fonction publique mise à jour (User $user) { if ($user->wasChanged('status')) { Mail::to($user)->send(new AccountStatusChanged($utilisateur)); $this->salesforce->updateContact($user->salesforce_id, ['status' => $user->status]); $this->auditLogger->log('status_change', $user, $user->getOriginal('status'), $user->status); if ($user->status === 'baratté') { $this->slack->notify('#customer-success', "Client {$user->name} baratté"); $this->analytics->track('customer_churned', $user); } if ($user->status === 'active' && $user->getOriginal('status') === 'trial') { $this->analytics->track('trial_converted', $user); } } if ($user->wasChanged('plan')) { $this->stripe->updateSubscription($user->stripe_subscription_id, [ 'price' => $user->plan->stripe_price_id, ]); $this->auditLogger->log('plan_change', $user, $user->getOriginal('plan_id'), $user->plan_id); $this->salesforce->updateContact($user->salesforce_id, ['plan' => $user->plan->name]); if ($user->plan->price > $user->getOriginal('plan')->price) { $this->slack->notify('#sales', "Mise à niveau : {$user->name} déplacé vers {$user->plan->name}"); } } if ($user->wasChanged('email')) { $this->mailingList->updateSubscriber($user->getOriginal('email'), $user->email); Mail::to($user->getOriginal('email'))->send(new EmailChangedNotification($user)); $this->auditLogger->log('email_change', $user, $user->getOriginal('email'), $user->email); } if ($user->wasChanged(['name', 'phone', 'company'])) { $this->salesforce->updateContact($user->salesforce_id, $user->only(['name', 'phone', 'company'])); } if ($user->isHighValue() && $user->isDirty()) { $this->slack->notify('#account-managers', "Le client de grande valeur {$user->name} a mis à jour son profil"); } // ... 150 lignes supplémentaires } }
Entrer ...
[Courte citation de 8% de l'article original]
Loading...