Le problème de l'exécution synchrone
En PHP traditionnel, le code s'exécute de manière synchrone : chaque instruction attend la fin de la précédente. Problématique quand une opération prend plusieurs secondes :
<?php
public function sendNotification(User $user)
{
$this->emailService->sendWelcomeEmail($user); // 4 secondes
$this->smsService->sendConfirmation($user); // 2 seconde
$this->analytics->trackAction($user); // 1 seconde
// Total : 7 secondes d'attente pour l'utilisateur !
return $this->render('confirmation.html.twig');
}Résultat : L'utilisateur attend devant un écran qui charge.
Pour résoudre ce problème on peut utiliser "Symfony Messenger" afin de décaler l’exécution des scripts lourd.
Mise en place de Symfony Messenger
Symfony Messenger est déjà assez bien décrit sur sa documentation officielle. Nous allons nous concentrer sur la partie code.
Dans le suite de ce tutoriel vous auriez des extraits de code donc il faudra ajuster à votre environnement.
1- On crée un handler Symfony Messenger
Le Handler est la classe qui contient le code PHP exécuté de manière asynchrone. C'est ici que vous placez la logique métier qui doit s'exécuter en arrière-plan.
<?php
namespace App\MessageHandler;
use App\Message\CheckMessageRead;
use App\Repository\MessageRepository;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Notifier\NotifierInterface;
Use Doctrine\ORM\EntityManagerInterface;
#[AsMessageHandler]
class CheckMessageReadHandler {
public function __construct(private MessageRepository $messageRepository, private NotifierInterface $notifier, private EntityManagerInterface $em) {
}
public function __invoke(CheckMessageRead $messageCheck): void {
// votre logique metier.
}
}2- On crée le conteneur de données
Cette classe est le "colis" qui transporte les données nécessaires à l'exécution asynchrone. Elle contient toutes les informations dont le Handler aura besoin pour faire son travail.
Le Message est comme une enveloppe qui contient les instructions et données, tandis que le Handler est le service postal qui traite cette enveloppe.
<?php
namespace App\Message;
class CheckMessageRead {
public function __construct(public readonly int $messageId, public readonly string $routeName) {
}
public function getMessageId() {
return $this->messageId;
}
public function getRouteName() {
return $this->routeName;
}
}2- On crée le conteneur de données
php bin/console debug:messenger
/etc/systemd/system/
php bin/console cache:clear --env=prod
php bin/console cache:clear --env=dev
Reconstruit les caches :
php bin/console cache:warmup
php bin/console cache:warmup --env=prod