Example below acts like pre-update database triggers where we log all activities made by users for auditing, reporting or security reasons. If someone changes the value from X to Y in a controller or a service class, this event listener records everything in another table in database.


Listeners.yml


services:
application_backend.event_listener.user_entity_audit:
class: Application\BackendBundle\EventListener\UserEntityAuditListener
arguments: [ @security.context ]
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: postFlush }

UserEntityAuditListener


namespace Application\BackendBundle\EventListener;

use Application\BackendBundle\Entity\User;
use Application\BackendBundle\Entity\UserAudit;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Security\Core\SecurityContextInterface;

class UserEntityAuditListener
{
private $securityContext;
private $fields = ['username', 'password'];
private $audit = [];

public function __construct(SecurityContextInterface $securityContextInterface)
{
$this->securityContext = $securityContextInterface;
}

public function preUpdate(PreUpdateEventArgs $args) // OR LifecycleEventArgs
{
$entity = $args->getEntity();

if ($entity instanceof User) {
foreach ($this->fields as $field) {
if ($args->getOldValue($field) != $args->getNewValue($field)) {
$audit = new UserAudit();
$audit->setField($field);
$audit->setOld($args->getOldValue($field));
$audit->setNew($args->getNewValue($field));
$audit->setUser($this->securityContext->getToken()->getUsername());

$this->audit[] = $audit;
}
}
}
}

public function postFlush(PostFlushEventArgs $args)
{
if (! empty($this->audit)) {
$em = $args->getEntityManager();

foreach ($this->audit as $audit) {
$em->persist($audit);
}

$this->audit = [];
$em->flush();
}
}
}