Бесконечный цикл PostPersist & PostFlush в Symfony - PullRequest
0 голосов
/ 31 мая 2018

Я пытаюсь связать профиль кофе с пользователем после того, как пользователь находится в базе данных.Эти данные профиля кофе находятся в сеансе, и я использую этот сеанс в 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 голосов
/ 31 мая 2018

В вашем postFlush событии вы снова покраснели.Вот что вызывает бесконечный цикл, потому что событие postFlush запускается каждый раз, когда вы вызываете метод flush.

Я не уверен, чего вы пытаетесь достичь, но ваша цель - создатьпотребление кофе каждый раз, когда вы сохраняете пользователя, вы можете добавить такой тест в начале вашего метода:

$entity = $args->getObject();

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

Это предотвратит бесконечный цикл.

ИЕще несколько вещей:

  • Ваш postPersist метод кажется бесполезным.Он будет вызываться каждый раз, когда объект сохраняется, поэтому ваше свойство $this->user не обязательно будет объектом пользователя.
  • Если вам нужен пользователь, вам не нужно извлекать его из своей базы данных.Просто используйте $args->getObject(), чтобы получить очищенную сущность.В дополнение к описанному выше тесту вы будете уверены, что метод вернет вам объект User.
  • Это не очень хорошая практика, чтобы проверить, вошел ли пользователь в ваш прослушиватель Doctrine.Это не то, что должен делать класс.
  • Не вставляйте контейнер в ваш конструктор.Вводите только то, что вам нужно (в данном случае ... ничего?)
0 голосов
/ 31 мая 2018

Вы вызываете $em->flush() внутри вашего события postPersist, в документах указано, что:

postFlush вызывается в конце EntityManager # flush ().EntityManager # flush () нельзя безопасно вызывать внутри своих слушателей.

Вам следует использовать другие события, такие как prePersist или postPersist.

Если возможно, попытайтесь избежать множественных flush() по одному запросу.

кстати, в этом нет необходимости, поскольку ваш пользовательский объект уже содержится внутри переменной $ user.

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

...