Symfony2 Doctrine Event Listener preUpdate methodMaximum function nesting level错误
Symfony2 Doctrine Event Listener preUpdate methodMaximum function nesting level error
用户密码更改事件可以使用 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:
- Changes to associations of the passed entities are not recognized by the flush operation anymore.
- 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.
- 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
,但在 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();
}
用户密码更改事件可以使用 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:
- Changes to associations of the passed entities are not recognized by the flush operation anymore.
- 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.- Any calls to
EntityManager#persist()
orEntityManager#remove()
, even in combination with the UnitOfWork API are strongly discouraged and don’t work as expected outside the flush operation.
作为解决方案,您可以在 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();
}