php - Symfony2 Doctrine Event Listener preUpdate methodMaximum function nesting level错误

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

最佳答案

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

Restrictions for this event:

  1. Changes to associations of the passed entities are not recognized by the flush operation anymore.
  2. Changes to fields of the passed entities are not recognized by the flush operation anymore, use the computed change-set passed to the event to modify primitive field values, e.g. use $eventArgs->setNewValue($field, $value); as in the Alice to Bob example above.
  3. Any calls to EntityManager#persist() or EntityManager#remove(), even in combination with the UnitOfWork API are strongly discouraged and don’t work as expected outside the flush operation.

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

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

关于php - Symfony2 Doctrine Event Listener preUpdate methodMaximum function nesting level错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28771704/

相关文章:

php - 删除按钮错误 jQuery

javascript - 新的 Instagram 强制执行签名请求与签名 header

php - 在 Cookie 中存储长数组

Mysql DISTINCT 和 ORDER BY 不起作用

javascript - Js 和 css 文件未加载到 Symfony 3 上的虚拟主机上

php - 如何使 NetBeans IDE 9 与 PHP 一起使用?

php - 如何在codeigniter join()方法中编写mysql函数

两次选择的MySQL连接结果

symfony - 在生产中使用 symfony/dotenv 包

symfony - 在 Symfony 2.7.3 中从数据库中获取对象