PostPersist& Symfony中的PostFlush无限循环

时间:2018-05-31 09:09:43

标签: symfony doctrine flush persist

我正在尝试在用户进入数据库后将咖啡配置文件链接到用户。 这个咖啡个人资料数据在会话中,我在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');
        }
    }

}

Services.yml:

    zpadmin.listener.user:
    class: AppBundle\EventListener\UserListener
    arguments: ['@service_container']
    tags:
        - { name: doctrine.event_listener, event: postPersist }
        - { name: doctrine.event_listener, event: postFlush }

导致此循环的原因是什么?如何解决?

2 个答案:

答案 0 :(得分:1)

您在postPersist活动中呼叫$em->flush(),在docs中声明:

  

在EntityManager #flush()结束时调用postFlush。   无法在侦听器内安全地调用EntityManager#flush()。

您应该使用其他活动,例如prePersistpostPersist

如果可能,请尝试在单个请求中避免多个flush()

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

  

$ us =   $ EM-&GT; getRepository(&#39;的appbundle:用户&#39;) - &GT; findOneById($这 - &GT;用户&GT;的getId());

答案 1 :(得分:1)

在你的postFlush事件中,你再次冲了过来。这就是导致无限循环的原因,因为每次调用postFlush方法时都会触发flush事件。

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

$entity = $args->getObject();

if (!$entity instanceof User) {
    return;
}

这将阻止无限循环。

还有一些事情:

  • 您的postPersist方法似乎毫无用处。每次持久化对象时都会调用它,因此您的$this->user角色不一定是用户对象。
  • 如果您需要该用户,则无需在数据库中获取它。只需使用$args->getObject()即可获得刷新的实体。除了上面的测试之外,您还可以确定该方法将返回一个User对象。
  • 检查用户是否已在您的Doctrine侦听器中登录,这不是一个很好的做法。这不是班级应该做的。
  • 不要在构造函数中注入容器。只注入你需要的东西(在这种情况下......什么都没有?)