Reputation: 5084
I have eventlistener preUpdate
public function preUpdate(PreUpdateEventArgs $args) {
$user = $args->getEntity();
if($user instanceof \iTracker\UserBundle\Entity\User) {
if($args->hasChangedField('userGroup')) {
$old = $args->getOldValue('userGroup');
$new = $args->getNewValue('userGroup');
$em = $args->getEntityManager();
$old->setAmount($old->getAmount() - 1);
$em->persist($old);
$new->setAmount($new->getAmount() + 1);
$em->persist($new);
$em->flush();
}
}
}
And after submiting form i get FatalErrorException: Error: Maximum function nesting level of '100' reached, aborting! in /var/www/issue/app/cache/dev/classes.php line 6123
in /var/www/issue/app/cache/dev/classes.php line 6123 at ErrorHandler->handleFatal() in /var/www/issue/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php line 0 at NormalizerFormatter->normalize() in /var/www/issue/app/cache/dev/classes.php line 6198 at LineFormatter->normalize() in /var/www/issue/app/cache/dev/classes.php line 6112 at NormalizerFormatter->format() in /var/www/issue/app/cache/dev/classes.php line 6172 at LineFormatter->format() in /var/www/issue/app/cache/dev/classes.php line 6320 at AbstractProcessingHandler->handle() in /var/www/issue/app/cache/dev/classes.php line 6646 at Logger->addRecord() in /var/www/issue/app/cache/dev/classes.php line 6710 at Logger->debug() in /var/www/issue/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php line 72 at DbalLogger->log() in /var/www/issue/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php line 50 at DbalLogger->startQuery() in /var/www/issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/LoggerChain.php line 50 at LoggerChain->startQuery() in /var/www/issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 774 at Connection->executeUpdate() in /var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 447 at BasicEntityPersister->_updateTable() in /var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 357 at BasicEntityPersister->update() in /var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 984 at UnitOfWork->executeUpdates() in /var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 317 at UnitOfWork->commit() in /var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 355 at EntityManager->flush() in /var/www/issue/src/iTracker/UserBundle/Listener/UserGroupAmount.php line 41 and this
and this 5 errors are looped, which cause this exception
Upvotes: 2
Views: 3723
Reputation: 1916
@meze is right, using flush inside the *Flush* events will cause a loop.
But there is a quick workaround that will allow you to do it still: $eventManager = $this -> em -> getEventManager();
// Remove event, if we call $this->em->flush() now there is no infinite recursion loop!
$eventManager -> removeEventListener('onFlush', $this);
// ...
// Re-attach since we're done
$eventManager -> addEventListener('onFlush', $this);
Seen on: Doctrine2 Event Listener: persisting in onFlush() | Benedikt Wolters
Upvotes: 3
Reputation: 15087
Calling flush
suggested by the author is not a correct solution. It will fire onFLush twice and create unneeded savepoints in transaction.
All additional changes can be scheduled in events using computeChangeSet
, recomputeSingleEntityChangeSet
and scheduleExtraUpdate
methods.
In case with a different entity:
public function preUpdate(PreUpdateEventArgs $args) {
$user = $args->getEntity();
if($user instanceof \iTracker\UserBundle\Entity\User) {
if($args->hasChangedField('userGroup')) {
$old = $args->getOldValue('userGroup');
$new = $args->getNewValue('userGroup');
$oldOriginAmount = $old->getAmount();
$newOriginAmount = $new->getAmount();
$old->setAmount($old->getAmount() - 1);
$uow->scheduleExtraUpdate($old, array(
'amount' => array($oldOriginAmount, $old->getAmount())
));
$new->setAmount($new->getAmount() + 1);
$uow->scheduleExtraUpdate($new, array(
'amount' => array($newOriginAmount, $new->getAmount())
));
}
}
}
Calling persist
is not needed (because the associated entites aren't created in any event, they should be already persistent).
Upvotes: 2