Les évènements — Formation Symfony 7
Dans le cadre d’une application complexe on a souvent besoin de rajouter de la logique supplémentaire sur des logiques déjà existantes. Pour répondre à cette problématique Symfony propose un système d’évènements qui permettra d’ajouter des écouteurs pour venir greffer la logique que l’on souhaite.
Emettre un évènement
Un évènement est une simple classe PHP que l’on va en général construire avec les éléments significatifs.
<?php
namespace App\Event;
use App\DTO\ContactDTO;
class ContactRequestEvent
{
public function __construct(public readonly ContactDTO $data){
}
}
Ensuite on pourra émettre cet évènement via l’EventDispatcher.
#[Route("https://grafikart.fr/contact", name: 'contact')]
public function contact(Request $request, MailerInterface $mailer, EventDispatcherInterface $dispatcher): Response
{
$data = new ContactDTO();
$form = $this->createForm(ContactType::class, $data);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$dispatcher->dispatch(new ContactRequestEvent($data));
$this->addFlash('success', 'Votre email a bien été envoyé');
} catch (\Exception $e) {
$this->addFlash('danger', 'Impossible d\'envoyer votre email');
}
}
return $this->render('contact/contact.html.twig', [
'form' => $form,
]);
}
Ecouteur d’évènement
Maintenant, si on souhaite ajouter de la logique lorsque cet évènement se produit on peut créer un listener. Cela peut se faire facilement à l’aide de l’attribut AsEventListener.
#[AsEventListener]
final class ContactListener
{
public function __invoke(ContactRequestEvent $event): void
{
// ...
}
}
Il est aussi possible de définir un Subscriber dans le cas où on veut pouvoir ajouter une logique similaire à plusieurs évènements.
<?php
namespace App\EventSubscriber;
use App\Entity\User;
use App\Event\ContactRequestEvent;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class MailingSubscriber implements EventSubscriberInterface
{
public function __construct(private readonly MailerInterface $mailer){
}
public function onContactRequestEvent(ContactRequestEvent $event): void
{
$data = $event->data;
$mail = (new TemplatedEmail())
->to($data->service)
->from($data->email)
->subject('Demande de contact')
->htmlTemplate('emails/contact.html.twig')
->context(['data' => $data]);
$this->mailer->send($mail);
}
public function onLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if (!$user instanceof User) {
return;
}
$mail = (new Email())
->to($user->getEmail())
->from('support@demo.fr')
->subject('Connexion')
->text('Vous vous êtes connecté');
$this->mailer->send($mail);
}
public static function getSubscribedEvents(): array
{
return [
ContactRequestEvent::class => 'onContactRequestEvent',
InteractiveLoginEvent::class => 'onLogin',
];
}
}