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




Вы вызываете $em->flush() внутри своего события postPersist, в документы указано, что:
postFlush is called at the end of EntityManager#flush(). EntityManager#flush() can NOT be called safely inside its listeners.
Вам следует использовать другие события, такие как prePersist или postPersist.
По возможности старайтесь избегать использования нескольких flush() в одном запросе.
кстати, в этом нет необходимости, потому что ваш пользовательский объект уже содержится внутри вашей переменной $ user.
$us = $em->getRepository('AppBundle:User')->findOneById($this->user->getId());
В вашем событии postFlush вы снова промываетесь. Это то, что вызывает бесконечный цикл, потому что событие postFlush запускается каждый раз, когда вы вызываете метод flush.
Я не уверен, чего вы пытаетесь достичь, но ваша цель - создавать потребление кофе каждый раз, когда вы спасаете пользователя, вы можете добавить тест, подобный этому, в начале вашего метода:
$entity = $args->getObject();
if (!$entity instanceof User) {
return;
}
Это предотвратит бесконечный цикл.
И еще несколько вещей:
postPersist кажется бесполезным. Он будет вызываться каждый раз, когда объект сохраняется, поэтому ваш $this->user не обязательно будет объектом User.$args->getObject(), чтобы получить сброшенный объект. В дополнение к приведенному выше тесту вы будете уверены, что метод вернет вам объект User.Postflush использует PostFlushEventArgs вместо LifecycleEventArgs. PostFlushEventArgs не содержит пользовательского объекта. Должен ли я использовать postflush для моего случая postpersist? И как мне очистить профиль кофе, который должен быть связан с пользователем, если я не могу использовать flush ()?
@MarcoKoopman Хорошее замечание. Вместо этого вы должны использовать postUpdate. Вы можете использовать метод flush в своем мероприятии, но вы не можете использовать его для объекта User, если вам не нужен бесконечный цикл.
Я изменил его на postUpdate, и теперь он работает как шарм! Большое спасибо! Я уже некоторое время борюсь с этой проблемой!
Если я не использую flush () в postPersist, он не помещает профиль кофе в базу данных. Но если я использую flush () в postPersist, я получаю сообщение об ошибке ..