【问题标题】:Symfony2 Doctrine Event Listener preUpdate methodMaximum function nesting level errorSymfony2 Doctrine Event Listener preUpdate 方法最大函数嵌套级别错误
【发布时间】:2015-04-30 13:21:38
【问题描述】:

用户密码更改事件可以使用 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

我的更新前监听器代码如下:

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 方法做到这一点吗?

【问题讨论】:

  • 最好使用 Symfony 事件系统并发送一个 CHANGED_PASSWORD 事件。 Symfony 2 事件监听器会负责记录它。您也可以通过添加自定义事件来使用 Doctrine 事件侦听器。但是preUpdate有很多限制。
  • 我正在使用 prePersist,preRemove 和 Doctrine 事件监听器没有出现问题。但是,在 preUpdate 方法上有一个问题。我可以从 passwordChange 函数调用 log 函数,但我想清理代码。
  • doctrine-orm.readthedocs.org/en/latest/reference/… "强烈建议不要对 EntityManager#persist() 或 EntityManager#remove() 进行任何调用,即使与 UnitOfWork API 结合使用,也不会在刷新操作之外按预期工作。
  • 好的,谢谢,我会用不同的方法。

标签: php mysql symfony doctrine-orm doctrine


【解决方案1】:

Doctrine 事件系统文档。 http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preupdate

此活动的限制:

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

作为一种解决方案,您可以在preUpdate 中获取changeSet,但在postUpdate 中调用EntityManager#persist()EntityManager#flush()

此外,您还需要使用监听器 $event 的私有属性在 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();
}

【讨论】:

    猜你喜欢
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2014-04-10
    • 2016-08-03
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    相关资源
    最近更新 更多