Symfony2 Doctrine事件监听器preUpdate方法最大函数嵌套级别错误

时间:2015-02-27 18:17:00

标签: php mysql symfony doctrine-orm doctrine

用户密码更改事件可以使用Doctrine preUpdate侦听器进行处理,但我无法执行另一个日志持久化过程,这会导致侦听器循环,因此错误跟踪如下所示:

Error: Maximum function nesting level of '5000' reached, aborting! in /var/www/my_project/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php line 85

我的preUpdate侦听器代码如下:

public function preUpdate(LifecycleEventArgs $args)
{
    if (php_sapi_name()!='cli') {

        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        // perhaps you only want to act on some "User" entity
        if ($entity instanceof User) {

            if($args->hasChangedField('password')){
                //log as eventlog
                $event = new \My_Project\UserBundle\Entity\EventLog();
                $event->setEventInfo(UserEventLogParams::$PASSWORD_CHANGE);
                $event->setIp($this->container->get('request')->getClientIp());
                $event->setUserId($entity->getId());
                $entityManager->persist($event);

                $entityManager->flush();
            }
        }
    }
}

这个问题在那里Adding additional persist calls to preUpdate call in Symfony 2.1进行了调整,但没有得到有效解决方案的回答。

如何使用Doctrine2事件监听器登录(使用mysql)密码更改事件?

我可以使用postUpdate方法吗?

1 个答案:

答案 0 :(得分:0)

Doctrine Event System文档。 http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preupdate

  

此活动的限制:

     
      
  1. 刷新操作无法识别对已传递实体的关联的更改。
  2.   
  3. 对已传递实体的字段的更改不再被刷新操作识别,使用传递给事件的计算变更集来修改原始字段值,例如,像上面的Alice to Bob示例一样使用$eventArgs->setNewValue($field, $value);
  4.   
  5. 强烈建议不要对EntityManager#persist()EntityManager#remove()进行任何调用,即使与UnitOfWork API结合使用,也不会在刷新操作之外按预期工作。
  6.   

作为解决方案,您可以在changeSet中抓取preUpdate,但在EntityManager#persist()中呼叫EntityManager#flush()postUpdate

另外,您需要使用监听器$事件的私有属性来获取postUpdate函数。

privat $event;

public function preUpdate(LifecycleEventArgs $args)
{
if (php_sapi_name()!='cli') {

    $entity = $args->getEntity();
    $entityManager = $args->getEntityManager();

    // perhaps you only want to act on some "User" entity
    if ($entity instanceof User) {

        if($args->hasChangedField('password')){
            //log as eventlog
            $this->event = new \My_Project\UserBundle\Entity\EventLog();
            $this->event->setEventInfo(UserEventLogParams::$PASSWORD_CHANGE);
            $this->event->setIp($this->container->get('request')->getClientIp());
            $this->event->setUserId($entity->getId());

        }
    }
}
}

public function postUpdate(LifecycleEventArgs $args)
{
    $entityManager = $args->getEntityManager();
    $entityManager->persist($this->event);
    $entityManager->flush();
}