Search code examples
phpsymfonydoctrine-ormsymfony4event-listener

Symfony - multiple arguments for different status in EventListener


I am using Symfony Doctrine Events to trigger notification after entity status update.

I want it triggered on postUpdate() of existing entity. I have defined constants of the selected status and want it recognized before message is triggered.

const TRIAL = 'trial';
const PAID = 'paid';
const DELETED = 'deleted';

public function postUpdate(LifecycleEventArgs $args)
{
    $this->handle($args, self::TRIAL);
}

/**
 * @param $args
 * @param $action
 */
private function handle($args, $action)
{
    /** @var EntityManagerInterface $entityManager */
    $entityManager = $args->getEntityManager();
    $uow = $entityManager->getUnitOfWork();
    $entity = $args->getObject();
    $changes = $uow->getEntityChangeSet($entity);

    if ((!$entity instanceof User) || (!array_key_exists("status", $changes))) {
        return;
    }

    $email = $entity->getEmail();
    $status = $entity->getStatus();
    $msg = null;

    if ($action == self::TRIAL) {
        $msg = "{$email} launched with status {$status}";
    }

    if ($action == self::PAID) {
        $msg = "{$email} launched with status {$status}";
    }

    if ($action == self::DELETED) {
        $msg = "{$email} launched with status {$status}";
    }

    try {
        $this->msgService->pushToChannel($this->msgChannel, $msg);
    } catch (\Exception $e) {
        $this->logger->error($e->getMessage());
    }
}

Can listener methods receive an changed status argument to display proper message? Can we have multiple arguments so Symfony can distinguish which status to use?

Like:

$this->handle($args, self::TRIAL);
$this->handle($args, self::PAID);
$this->handle($args, self::DELETED);

Solution

  • Try to check the $changes, like that (not tested, but you'll get the idea):

    const TRIAL = 'trial';
    const PAID = 'paid';
    const DELETED = 'deleted';
    
    public function postUpdate(LifecycleEventArgs $args)
    {
        $this->handle($args);
    }
    
    /**
     * @param $args
     */
    private function handle($args)
    {
        /** @var EntityManagerInterface $entityManager */
        $entityManager = $args->getEntityManager();
        $uow = $entityManager->getUnitOfWork();
        $entity = $args->getObject();
        $changes = $uow->getEntityChangeSet($entity);
    
        if ((!$entity instanceof User) || (!array_key_exists("status", $changes))) {
            return;
        }
    
        $email = $entity->getEmail();
        $msg = null;
    
        // Check if the status has changed
        if(!empty($changes["status"])){
            // $changes["status"] contain the previous and the new value in an array like that ['previous', 'new']
            // So whe check if the new value is one of your statuses
            if(in_array($changes["status"][1], [self::TRIAL, self::PAID, self::DELETED])) {
                $msg = "{$email} launched with status {$status}";
            }
        }
    
        try {
            $this->msgService->pushToChannel($this->msgChannel, $msg);
        } catch (\Exception $e) {
            $this->logger->error($e->getMessage());
        }
    }