首页 文章

symfony2达到'100'的最大函数嵌套级别,正在中止!与学说eventlistener

提问于
浏览
1

我有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();
        }
    }
}

提交表格后我得到 FatalErrorException: Error: Maximum function nesting level of '100' reached, aborting! in /var/www/issue/app/cache/dev/classes.php line 6123

位于/ var / www / issue / vendor / vendor / symfony / symfony / src / Symfony / Component / HttpKernel / Debug中的/var/www/issue/app/cache/dev/classes.php第6123行的ErrorHandler-> handleFatal() /ErrorHandler.php第0行在NormalizerFormatter-> normalize()在/var/www/issue/app/cache/dev/classes.php第6198行的LineFormatter-> normalize()在/ var / www / issue / app / cache中/dev/classes.php第6112行在NormalizerFormatter-> format()in /var/www/issue/app/cache/dev/classes.php第6172行在LineFormatter-> format()在/ var / www / issue / app /cache/dev/classes.php第6320行在AbstractProcessingHandler-> handle()in /var/www/issue/app/cache/dev/classes.php第6646行,Logger-> addRecord()在/ var / www / issue /app/cache/dev/classes.php 6710在Logger-> debug()/ dvarLogger /var/www/issue/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php第72行 - > / var / www / www / issue / vendor中的/var/www/issue/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php第50行DbalLogger-> startQuery() / doctri在/var/www/issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php第774行的LoggerChain-> startQuery()中的ne / dbal / lib / Doctrine / DBAL / Logging / LoggerChain.php第50行Connection-> executeUpdate()位于/ var / www / issue / vendor /中的/var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php第447行的BasicEntityPersister - > _ updateTable()在/var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php第984行的BasicEntityPersister-> update()中的doctrine / orm / lib / Doctrine / ORM / Persisters / BasicEntityPersister.php第357行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 / EntmManager中的orm / lib / Doctrine / ORM / EntityManager.php第355行 - > /var/www/issue/src/iTracker/UserBundle/Listener/UserGroupAmount.php第41行中的flush()

  • at UserGroupAmount-> preUpdate()/var/www/issue/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php第61行

  • 在ContainerAwareEventManager-> dispatchEvent()/var/www/issue/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php 980行

  • 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第355行

  • at EntityManager-> flush / in in /var/www/issue/src/iTracker/UserBundle/Listener/UserGroupAmount.php第41行

并且这5个错误是循环的,这会导致此异常

2 回答

  • 2

    调用作者提出的 flush 不是一个正确的解决方案 . 它将触发onFLush两次并在事务中创建不需要的保存点 .

    可以使用 computeChangeSetrecomputeSingleEntityChangeSetscheduleExtraUpdate 方法在事件中安排所有其他更改 .

    如果是不同的实体:

    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())
                ));
            }
        }
    }
    

    不需要调用 persist (因为在任何情况下都不会创建关联的entites,它们应该已经是持久的) .

  • 2

    @meze是对的,在* Flush *事件中使用flush将导致循环 .

    但是有一个快速的解决方法,允许你仍然这样做:$ 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);
    

    见:Doctrine2 Event Listener: persisting in onFlush() | Benedikt Wolters

相关问题