I have a onFlush() event which works fine but what I need to do is to turn that into preFlush() or preUpdate() both acceptable. I did preFlush() but for some reason it doesn't do anything. Not even an error. What am I missing?
TEST: I placed exit
in preFlush()
to see if it is being called at all or not. Outcome is: 1 so foreach()
is never run! It is an empty array. I also tested preUpdate() and all the lines in that get runed but no data inserted.
public function preFlush(PreFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
echo '1';
foreach ($uow->getScheduledEntityUpdates() as $entity) {
echo '2';
if ($entity instanceof User) {
echo '3';
}
}
exit;
}
I created them after reading the documentation.
service.yml
services:
entity.event_listener.user:
class: Site\FrontBundle\EventListener\Entity\UserListener
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: onFlush }
- { name: doctrine.event_listener, event: preFlush }
Working onFlush() example:
class UserListener
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$em->persist($userLog);
// Instead of $em->flush() cos we're already in flush process
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
}
Not working preFlush() example:
class UserListener
{
public function preFlush(PreFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$em->persist($userLog);
// Instead of $em->flush() cos we're already in flush process
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
}
Not working preUpdate() example
class UserListener
{
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ') been updated.');
$em = $args->getEntityManager();
$em->persist($userLog);
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
SOLUTION:
The trick is, persisting after preUpdate()
within postFlush()
event.
Note: Although this might not be the best solution, it answers the question however it could be done with an Event Subscriber or simple onFlush()
-> $uow->getScheduledEntityUpdates()
in an Event Listener.
Service.yml
services:
entity.event_listener.user_update:
class: Site\FrontBundle\EventListener\Entity\UserUpdateListener
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: postFlush }
Event Listener
<?php
namespace Site\FrontBundle\EventListener\Entity;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Site\FrontBundle\Entity\User;
use Site\FrontBundle\Entity\UserLog;
class UserUpdateListener
{
private $log = array();
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// False check is compulsory otherwise duplication occurs
if (($entity instanceof User) === false) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$this->log[] = $userLog;
}
}
public function postFlush(PostFlushEventArgs $args)
{
if (! empty($this->log)) {
$em = $args->getEntityManager();
foreach ($this->log as $log) {
$em->persist($log);
}
$em->flush();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With