Циркулярная ссылка на preFlush

У меня проблемы с инъекцией зависимостей. Я пытаюсь сохранить запись в БД в моем прослушивателе preFlush. Я сохраняю эту запись в БД через свой собственный сервис (пользовательский сервис регистрации). Я пробовал это несколькими способами, но ни один из них не работает, я пробовал каждый результат поиска Google / Stackover, но я не боюсь, пока.

Вот настройка для моего класса логгера, все частные переменные были опущены, но установлены (я использую стек запросов и переводчик где-то в классе, не был уверен, должен ли я пропустить этот вопрос):

Config:

core.logger:
class: xxx\CoreBundle\Logger
arguments: [@request_stack, @doctrine.orm.entity_manager, @translator]

Учебный класс:

public function __construct(RequestStack $requestStack, EntityManager $em, TranslatorInterface $t)
{
$this->requestStack = $requestStack;
$this->em = $em
$this->t = $t;
}
public function addLogEntityChange($uow, $entity) {
$changeset = $uow->getEntityChangeSet($entity);
foreach($changeset as $key => $value) {
$logEntity = new Log();
//setStuff..
$this->em->persist($logEntity);
}
$this->em->flush();
}

А вот мой интерфейсный код

Config:

xxxcore.loggerlistener:
class: xxx\CoreBundle\Listener\LoggerListener
calls:
- [ setLogger, [@core.logger] ]
tags:
- { name: doctrine.event_listener, event: preFlush }

Интерфейс:

    public function setLogger($logger)
{
$this->l = $logger;
}
public function preFlush(PreFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
$uow->computeChangeSets();

foreach ($uow->getScheduledEntityUpdates() as $entity) {
if($entity instanceof LoggerInterface) {
$this->l->addLogEntityChange($uow, $entity);
}

}
}

Это приводит к

Circular reference detected for service "doctrine.dbal.xxx_connection", path: "doctrine.dbal.xxx_connection".

Я попытался установить диспетчер сущностей в классе регистратора вручную, поэтому удалил внедрение зависимости и использовал функцию setEntityManager, но это просто тайм-аут страницы. Я попытался вставить service_container, но это тоже не помогло.

При вызове функций вручную после того, как я сохраняю сущность, все это работает, но я хотел бы автоматизировать это через интерфейс с прослушивателем preFlush.

Любая помощь / понимание будет принята с благодарностью!

2

Решение

Интересно. Это дошло до: Исключение циркулярной ссылки Symfony для службы прослушивания событий Doctrine onFlush

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

Я проверил код DoctrineBundle и да, менеджер сущностей зависит от его слушателей и, конечно, если слушатель зависит от менеджера сущностей, мы получаем циклическую ссылку.

Я продублировал проблему с:

## services.yml
cerad_project_level_logger:
class: Cerad\ProjectLevel\LevelLogger
arguments:
# - '@doctrine.orm.entity_manager'

cerad_project_level_listener:
class: Cerad\ProjectLevel\LevelListener
arguments:
- '@cerad_project_level_logger'
tags:
- { name: doctrine.event_listener, event: preFlush }

Обходной путь — передать менеджер сущностей в методе логгера, а не вводить его.

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
if($entity instanceof LoggerInterface) {
$this->l->addLogEntityChange($em, $uow, $entity);
}

Я вполне уверен, что ваш код все равно не будет работать должным образом, так как preFlush всегда вызывается после em-> flush, и вы попадете в цикл, но по крайней мере это обойдёт ошибку циклической ссылки.

Все эти проблемы исчезнут, если вы просто сделаете менеджера сущностей регистратора. Кроме того, вы действительно хотите войти в свою производственную базу данных?

2

Другие решения

Других решений пока нет …