Closed FabRiviere closed 1 year ago
symfony composer req doctrine-messenger
Lorsqu'une action doit être exécutée de manière asynchrone, envoyer un message à un bus messager . Le bus stocke le message dans un fichier d'attente et rend immédiatement la main pour permettre au flux des opérations de reprise aussi vite que possible.
<?php
namespace App\Message;
class CommentMessage
{
public function __construct(private int $id, private array $context = [],)
{
}
public function getId(): int
{
return $this->id;
}
public function getContext(): array
{{
return $this->context;
}}
}
Dans le monde de Messenger, nous n'avons pas de contrôleurs, mais des gestionnaires de messages.
Sous un nouvel espace de noms App\MessageHandler, créez une classe CommentMessageHandlerqui saura comment gérer les messages CommentMessage:
<?php
namespace App\MessageHandler;
use App\Message\CommentMessage;
use App\Repository\CommentRepository;
use App\Service\SpamChecker;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
class CommentMessageHandler
{
public function __construct(
private EntityManagerInterface $entityManager,
private SpamChecker $spamChecker,
private CommentRepository $commentRepository,
) {
}
public function __invoke(CommentMessage $message)
{
$comment = $this->commentRepository->find($message->getId());
if (!$comment) {
return;
}
if (2 === $this->spamChecker->getSpamScore($comment, $message->getContext())) {
$comment->setState('spam');
} else {
$comment->setState('published');
}
$this->entityManager->flush();
}
}
public function __construct(private EntityManagerInterface $entityManager, private MessageBusInterface $bus)
{
}
#[Route('/conference/{slug}', name: 'conference')]
public function show(Request $request, Conference $conference, CommentRepository $commentRepository,
#[Autowire('%photo_dir%')] string $photoDir): Response
{
$comment = new Comment();
$formComment = $this->createForm(CommentType::class, $comment);
$formComment->handleRequest($request);
if ($formComment->isSubmitted() && $formComment->isValid()) {
$comment->setConference($conference);
//! Traitement des photos
if ($photo = $formComment['photo']->getData()) {
$filename = bin2hex(random_bytes(6)).'.'.$photo->guessExtension();
$photo->move($photoDir, $filename);
$comment->setPhotoFilename($filename);
}
$this->entityManager->persist($comment);
$this->entityManager->flush();
//! vérification si présence de spam avant de stocker les commentaires en DB
$context = [
'user_ip' => $request->getClientIp(),
'user_agent' => $request->headers->get('user-agent'),
'referrer' => $request->headers->get('referer'),
'permalink' => $request->getUri(),
];
// ! mis en commentaire pour utilisation du MessageBusInterface à la place de SpamChecker
// if (2 === $spamChecker->getSpamScore($comment, $context)) {
// throw new \RuntimeException('Blatant spam, go away !! 😵💫😟');
// }
// $this->entityManager->flush();
// ! Utilisation du MessageBusInterface
$this->bus->dispatch(new CommentMessage($comment->getId(), $context));
return $this->redirectToRoute('conference', ['slug' => $conference->getSlug()]);
}
$offset = max(0, $request->query->getInt('offset', 0));
$paginator = $commentRepository->getCommentPaginator($conference, $offset);
return $this->render('conference/show.html.twig', [
'conference' => $conference,
'comments' => $paginator,
'previous' => $offset - CommentRepository::PAGINATOR_PER_PAGE,
'next' => min(count($paginator), $offset + CommentRepository::PAGINATOR_PER_PAGE),
'comment_form' => $formComment,
]);
}
Au lieu de dépendre du SpamChecker, nous envoyons maintenant un message dans le bus. Le gestionnaire décide alors ce qu'il en fait.
```
# Route your messages to the transports
'App\Message\CommentMessage': async