后波斯特;Symfony中的后刷新无限循环

后波斯特;Symfony中的后刷新无限循环,symfony,doctrine,flush,persist,Symfony,Doctrine,Flush,Persist,我试图在用户进入数据库后将咖啡配置文件链接到用户。 此咖啡配置文件数据位于会话中,我正在postFlush中使用此会话 然而,这段代码正在创建一个无限循环,我不知道为什么: UserListener.php: <?php namespace AppBundle\EventListener; use FOS\UserBundle\FOSUserEvents; use FOS\UserBundle\Event\FormEvent; use Symfony\Component\HttpFou

我试图在用户进入数据库后将咖啡配置文件链接到用户。 此咖啡配置文件数据位于会话中,我正在postFlush中使用此会话

然而,这段代码正在创建一个无限循环,我不知道为什么:

UserListener.php:

<?php

namespace AppBundle\EventListener;

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use AppBundle\Entity\Consumption;
use AppBundle\Entity\CoffeeOption;
use AppBundle\Entity\Consumeable;
use AppBundle\Entity\MomentPreference;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\Event\PostFlushEventArgs;

class UserListener
{
    private $container;
    private $user;

    public function __construct(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function postPersist(LifecycleEventArgs $args)
    {
        $user = $args->getEntity();

        $this->user = $user;
    }

    public function postFlush(PostFlushEventArgs $args)
    {
        $session = new Session();

        if($session) {

            $em = $args->getEntityManager();

            $us = $em->getRepository('AppBundle:User')->findOneById($this->user->getId());

            $consumption = $session->get('consumption');
            $coffee = $session->get('coffee');
            $moment = $session->get('moment');

            $consumption->setUser($us);

            //dummy data for the day, later this needs to be turned into datetime
            $moment->setDay('monday');
            $moment->setConsumption($consumption);

            $em->persist($consumption);
            $em->persist($coffee);
            $em->persist($moment);

            $em->flush();        

        } else {
            return $this->redirectToRoute('fos_user_registration_register');
        }
    }

}

是什么导致了此循环以及如何修复它?

您正在postPersist事件中调用
$em->flush()
,其中声明:

在EntityManager#flush()的末尾调用postFlush。 无法在其侦听器中安全地调用EntityManager#flush()

您应该使用其他事件,如
prePersist
postersist

如果可能的话,尽量避免对单个请求执行多个
flush()

顺便说一下,没有必要这样做,因为您的用户对象已经包含在$user变量中

美元= $em->getRepository('AppBundle:User')->findOneById($this->User->getId())


您正在postPersist事件中调用
$em->flush()
,声明如下:

在EntityManager#flush()的末尾调用postFlush。 无法在其侦听器中安全地调用EntityManager#flush()

您应该使用其他事件,如
prePersist
postersist

如果可能的话,尽量避免对单个请求执行多个
flush()

顺便说一下,没有必要这样做,因为您的用户对象已经包含在$user变量中

美元= $em->getRepository('AppBundle:User')->findOneById($this->User->getId())


postFlush
事件中,您再次刷新。这就是导致无限循环的原因,因为每次调用
flush
方法时都会触发
postfush
事件

我不确定您想要实现什么,但您的目标是每次保存用户时创建一个咖啡消费量,您可以在方法的开头添加这样的测试:

$entity = $args->getObject();

if (!$entity instanceof User) {
    return;
}
这将防止无限循环

还有几件事:

  • 您的
    postPersist
    方法似乎没有用。每次对象被持久化时都会调用它,因此您的
    $this->user
    属性不一定是用户对象
  • 如果需要用户,则不必在数据库中获取它。只需使用
    $args->getObject()
    获取刷新的实体。除了上面的测试之外,您将确保该方法将返回一个用户对象
  • 这不是检查用户是否登录到您的Doctrine侦听器的很好实践。这不是我们班应该做的
  • 不要将容器注入构造函数中。只注射你需要的(在这种情况下……什么都不注射?)

在您的
postFlush
事件中,您再次刷新。这就是导致无限循环的原因,因为每次调用
flush
方法时都会触发
postfush
事件

我不确定您想要实现什么,但您的目标是每次保存用户时创建一个咖啡消费量,您可以在方法的开头添加这样的测试:

$entity = $args->getObject();

if (!$entity instanceof User) {
    return;
}
这将防止无限循环

还有几件事:

  • 您的
    postPersist
    方法似乎没有用。每次对象被持久化时都会调用它,因此您的
    $this->user
    属性不一定是用户对象
  • 如果需要用户,则不必在数据库中获取它。只需使用
    $args->getObject()
    获取刷新的实体。除了上面的测试之外,您将确保该方法将返回一个用户对象
  • 这不是检查用户是否登录到您的Doctrine侦听器的很好实践。这不是我们班应该做的
  • 不要将容器注入构造函数中。只注射你需要的(在这种情况下……什么都不注射?)

Postflush使用PostFlushEventArgs而不是LifecycleEventArgs。PostFlushEventArgs中没有用户对象。我的postpersist案例是否应该使用postflush?当我不能使用flush()时,如何刷新需要链接到用户的咖啡配置文件?@MarcoKoopman很好。您应该使用postUpdate。你可以在你的事件中使用
flush
方法,但是如果你不想要无限循环,就不能在用户实体上使用它。我已经将它改为postUpdate,现在它就像一个符咒一样工作!非常感谢你!我为这个问题绞尽脑汁已经有一段时间了!Postflush使用PostFlusheEventArgs而不是LifecycleEventArgs。PostFlushEventArgs中没有用户对象。我的postpersist案例是否应该使用postflush?当我不能使用flush()时,如何刷新需要链接到用户的咖啡配置文件?@MarcoKoopman很好。您应该使用postUpdate。你可以在你的事件中使用
flush
方法,但是如果你不想要无限循环,就不能在用户实体上使用它。我已经将它改为postUpdate,现在它就像一个符咒一样工作!非常感谢你!我为这个问题绞尽脑汁已经有一段时间了!如果我在postPersist中不使用flush(),它不会将咖啡配置文件推送到数据库。但是如果我在postPersist中使用flush(),我会得到一个错误。如果我在postPersist中不使用flush(),它不会将咖啡配置文件推送到数据库。但是如果我在postPersist中使用flush(),我会得到一个错误。。