Search code examples
phpsymfonyemailevent-listenerlifecycle

Lifecycle callback postUpdate to send an email in Symfony


I'm trying to send an email when the entity is updating (and getVerified), I used the event Suscriber from doctrine, but I don't know exactly how to do that.

My MailEvent.php :

class MailEvent
 {
// the entity listener methods receive two arguments:
// the entity instance and the lifecycle event
public function postUpdate(Candidature $candidature, Annonce $annonce, MailerInterface $mailer, LifecycleEventArgs $event): void
{   
$change = $event->getEntityChangeSet();

if ($change instanceof Candidature and $candidature->getIsVerified()) {
    $email = (new Email())
        ->from('[email protected]')
        ->to($annonce->getEmail())
        ->subject('Vous avez un nouveau candidat !')
        ->text("{$candidature->getNom()} {$candidature->getPrenom()} a postulé à votre annonce, vous trouverez son CV en pièce jointe !")
        ->attachFromPath("public/uploads/images/{$candidature->getCv()}");
    ;
    $mailer->send($email);
}
}

If someone can help me understand, thank you.

EDIT: Problem solve! Thank you all ! MailEvent.php:

class MailEvent
{
  // the entity listener methods receive two arguments:
  // the entity instance and the lifecycle event

public function postUpdate(Candidature $candidature, LifecycleEventArgs $event)
{
    $request = $this->requestStack->getCurrentRequest();

     $entityManager = $this->entityManager;

    $annonce = $entityManager->getRepository(Annonce::class)->findOneBy([
       'id' => $request->get('id')
   ]);


    if ($candidature->getIsVerified()) {
    $email = (new Email())
    ->from('[email protected]')
    ->to($annonce->getEmail())
    ->subject('Vous avez un nouveau candidat !')
    ->text("{$candidature->getNom()} {$candidature->getPrenom()} a postulé à votre annonce, vous trouverez son CV en pièce jointe !")
    ->attachFromPath("public/uploads/images/{$candidature->getCv()}");
;
$this->mailer->send($email);
    }

}

public function __construct(
    private readonly EntityManagerInterface $entityManager,
    private readonly MailerInterface $mailer,
    private readonly RequestStack $requestStack
){

}

}


Solution

  • You need to make sure you register your listener in your services.yaml

        App\EventListener\MailEvent:
            tags:
                - name: 'doctrine.orm.entity_listener'
                  event: 'postUpdate'
                  entity: 'App\Entity\Candidature'
    

    Then you need the postUpdate function inside your listener,

        public function postUpdate(Candidature $candidature, LifecycleEventArgs $event): void
        {
    ...
        }
    

    It can only take 2 parameters, if you need access to services you need to use the dependency injection in the constructor :

        public function __construct(
            private readonly AnnonceRepository $annonceRepository,
            private readonly MailerInterface $mailer,
        ) {
        }
    

    Then you can use these inside your postUpdate function, I do not know how you get the related Annonce in your project but you could use the repository to go and fetch it from the database.

        public function postUpdate(Candidature $candidature, LifecycleEventArgs $event): void
        {
           //maybe ?
        $annonce = $this->annonceRepository->findOneBy["candidature" => $candidature];
    
    //This has to be a Candidature entity, as defined in the services.yaml, so no need to check that, you also do not use the changeset at all so no need for that either 
    
    if ($candidature->getIsVerified()) {
        $email = (new Email())
            ->from('[email protected]')
            ->to($annonce->getEmail())
            ->subject('Vous avez un nouveau candidat !')
            ->text("{$candidature->getNom()} {$candidature->getPrenom()} a postulé à votre annonce, vous trouverez son CV en pièce jointe !")
            ->attachFromPath("public/uploads/images/{$candidature->getCv()}");
        ;
        $this->mailer->send($email);
        }