Skip to Content

Terrain 12 — Async & temps réel

🔍 Renfort : Partie 12.

1. Message + handler ⭐⭐

🕹️ Mission : un message SendBookingConfirmation(int $bookingId) + son handler.

✅ Solution

final readonly class SendBookingConfirmation { public function __construct(public int $bookingId) {} } #[AsMessageHandler] final class SendBookingConfirmationHandler { public function __invoke(SendBookingConfirmation $m): void { /* recharge l'entité + envoie */ } }

2. Ids, pas d’entités ⭐⭐

🕹️ Mission : pourquoi transporter bookingId et non l’objet Booking ?

✅ Solution

Le message est sérialisé/désérialisé (file) ; une entité y est mal adaptée (état périmé, EM déconnecté). On transporte l’id et on recharge l’entité fraîche dans le handler.

3. Router en async ⭐⭐

🕹️ Mission : router SendBookingConfirmation vers un transport async.

✅ Solution

framework: messenger: routing: App\Message\SendBookingConfirmation: async

4. Consommer ⭐

🕹️ Mission : la commande pour traiter la file async.

✅ Solution

php bin/console messenger:consume async -vv (supervisé en prod).

5. Idempotence ⭐⭐⭐⭐

🕹️ Mission : pourquoi un handler de paiement doit-il être idempotent ?

✅ Solution

Un message peut être rejoué ; sans idempotence, on débiterait deux fois. Vérifier un état (isPaid()) ou une clé d’idempotence avant d’agir.

6. Scheduler ⭐⭐⭐

🕹️ Mission : envoyer les rappels chaque jour à 8h.

✅ Solution

RecurringMessage::cron('0 8 * * *', new SendDailyReminders())

(dans une Schedule fournie par #[AsSchedule].)

7. Email Twig ⭐⭐

🕹️ Mission : un e-mail de confirmation rendu par un template.

✅ Solution

(new TemplatedEmail())->to($email)->subject('Confirmée') ->htmlTemplate('emails/confirmation.html.twig')->context(['booking' => $b]);

8. Publier Mercure ⭐⭐⭐

🕹️ Mission : publier les places restantes d’un créneau sur son topic.

✅ Solution

$this->hub->publish(new Update( 'https://booklab.test/slots/' . $slot->getId(), json_encode(['seatsLeft' => $slot->getSeatsLeft()]), ));

9. Consommer Mercure (Next.js) ⭐⭐⭐

🕹️ Mission : avec quelle API navigateur s’abonne-t-on, et que ne pas oublier ?

✅ Solution

EventSource (SSE), dans un Client Component ; fermer la connexion (es.close()) au démontage (cleanup).

10. Confirmer un paiement Stripe ⭐⭐⭐⭐⭐

🕹️ Mission : où confirme-t-on réellement le paiement, et quelle vérification est indispensable ?

✅ Solution

Dans le webhook (checkout.session.completed), pas la redirection de succès ; avec vérification de la signature (constructEvent + secret) et un handler idempotent.


Terrain suivant : Interopérabilité.