关于 preFlush 的循环参考
Circular Reference on preFlush
我的依赖注入遇到了一些问题。我试图在我的 preFlush 侦听器中将记录保存到数据库。我正在通过我自己的服务(自定义日志记录服务)将此记录保存到数据库中。我已经尝试了几种方法,但 none 正在工作,我已经尝试了我发现的每一个 google / stackover 流结果,但恐怕还没有运气。
这是我的记录器 class 的设置,所有私有变量都已被省略但已设置(我在 class 中的其他地方使用请求堆栈和翻译器,不确定是否我应该省略这个问题):
配置:
core.logger:
class: xxx\CoreBundle\Logger
arguments: [@request_stack, @doctrine.orm.entity_manager, @translator]
Class:
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();
}
这是我的界面代码
配置:
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".
我已经尝试在记录器 class 中手动设置实体管理器,因此删除依赖注入并使用 setEntityManager 函数,但这只会使页面超时。我试过插入 service_container 但这也没有真正帮助。
当我持久化实体后手动调用函数时,一切正常,但我想通过与 preFlush 侦听器的接口自动执行此操作。
任何帮助/见解将不胜感激!
有意思。这以前出现过:Symfony Circular Reference Exception for Doctrine onFlush Event Listener Service
在学说标记过程中的某个地方,必须有一个编译器通道将侦听器注入实体管理器并导致循环引用。
我检查了 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 之后调用,您最终会陷入循环,但至少这会克服循环引用错误。
如果你只做一个记录器实体管理器,所有这些问题都会消失。此外,您真的要登录您的生产数据库吗?
我的依赖注入遇到了一些问题。我试图在我的 preFlush 侦听器中将记录保存到数据库。我正在通过我自己的服务(自定义日志记录服务)将此记录保存到数据库中。我已经尝试了几种方法,但 none 正在工作,我已经尝试了我发现的每一个 google / stackover 流结果,但恐怕还没有运气。
这是我的记录器 class 的设置,所有私有变量都已被省略但已设置(我在 class 中的其他地方使用请求堆栈和翻译器,不确定是否我应该省略这个问题):
配置:
core.logger:
class: xxx\CoreBundle\Logger
arguments: [@request_stack, @doctrine.orm.entity_manager, @translator]
Class:
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();
}
这是我的界面代码
配置:
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".
我已经尝试在记录器 class 中手动设置实体管理器,因此删除依赖注入并使用 setEntityManager 函数,但这只会使页面超时。我试过插入 service_container 但这也没有真正帮助。
当我持久化实体后手动调用函数时,一切正常,但我想通过与 preFlush 侦听器的接口自动执行此操作。
任何帮助/见解将不胜感激!
有意思。这以前出现过:Symfony Circular Reference Exception for Doctrine onFlush Event Listener Service
在学说标记过程中的某个地方,必须有一个编译器通道将侦听器注入实体管理器并导致循环引用。
我检查了 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 之后调用,您最终会陷入循环,但至少这会克服循环引用错误。
如果你只做一个记录器实体管理器,所有这些问题都会消失。此外,您真的要登录您的生产数据库吗?