Symfony 抛出 ServiceCircularReferenceException

Posted

技术标签:

【中文标题】Symfony 抛出 ServiceCircularReferenceException【英文标题】:Symfony throwing ServiceCircularReferenceException 【发布时间】:2018-07-21 06:07:38 【问题描述】:

我正在使用 Symfony 2.7,我正在根据以下教程将所有日志写入数据

https://nehalist.io/logging-events-to-database-in-symfony/

我在服务中

 monolog.db_handler:
        class: AppBundle\Util\MonologDBHandler
        arguments: ['@doctrine.orm.entity_manager']

在 monlog db 处理程序中我有以下内容

class MonologDBHandler extends AbstractProcessingHandler

    /**
     * @var EntityManagerInterface
     */
    protected $em;

    /**
     * MonologDBHandler constructor.
     * @param EntityManagerInterface $em
     */
    public function __construct(EntityManagerInterface $em)
    
        parent::__construct();
        $this->em = $em;
    

    /**
     * Called when writing to our database
     * @param array $record
     */
    protected function write(array $record)
    
        $logEntry = new Log();
        $logEntry->setMessage($record['message']);
        $logEntry->setLevel($record['level']);
        $logEntry->setLevelName($record['level_name']);
        $logEntry->setExtra($record['extra']);
        $logEntry->setContext($record['context']);

        $this->em->persist($logEntry);
        $this->em->flush();
    

如果我启用开发模式,我会收到以下错误

致命错误:未捕获 Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException: 检测到服务的循环参考 “doctrine.orm.default_entity_manager”,路径: “doctrine.orm.default_entity_manager -> 教义.dbal.default_connection -> monolog.logger.doctrine -> monolog.monolog.db_handler"。

我知道这个错误是由于服务原则注入造成的。我该如何解决这个问题。谢谢

【问题讨论】:

这篇文章是为 S3+ 写的。由于事件管理器依赖于它的所有侦听器,因此曾经有很多这样的问题。因此,使侦听器依赖于实体管理器将导致循环依赖。这在 3.x 中被清理了一点。甚至可能是2.8。不确定。我真正能建议的只是查看 2.7 文档以获取示例。 @Cerad.thanks 有什么解决方案可以解决这个问题。我无法升级 symfony,因为它必须改变很多东西 @Cerad.if 我禁用 prod false 然后工作正常。只有当我更改为 true 时才会抛出错误 我必须设置一个 2.7 的环境并搞砸一点。我确定可行的唯一方法是通过全局 $kernel 变量访问实体管理器。不是理想的解决方案,但可能是您最好的选择。 @Cerad.感谢您的努力。我是 symfony 的新手。如果你得到解决方案,请及时发布。谢谢 【参考方案1】:

这种方法是一个非常糟糕的主意,应该避免,但您可以通过全局 $kernel 变量访问实体管理器来摆脱循环引用。

class MonologDBHandler extends AbstractProcessingHandler

    public function __construct()
    
        parent::__construct();
    
    protected function write(array $record)
    
        global $kernel;
        $em = $kernel->getContainer()-get('doctrine.orm.entity_manager');

然后从您的服务定义中删除参数部分。

【讨论】:

出现致命错误:允许的内存大小为 536870912 字节已用完 我确实说过这是个坏主意:) 整篇文章似乎有点可疑。 write 方法可能在实体管理器被刷新时被触发,因此当您将日志对象写出时,它会再次刷新并循环。制作一个second entity manager 仅用于日志记录(可能使用第二个数据库),它可能会起作用。事实上,使用第二个实体管理器可能会让您的原始代码工作。

以上是关于Symfony 抛出 ServiceCircularReferenceException的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 3:渲染过程中抛出异常

Symfony/PhpUnit - 如何测试服务中是不是抛出异常

Symfony 2 acl isFieldGranted 抛出异常

Symfony 3 包创建总是抛出“编辑 composer.json 文件”

symfony 在渲染模板的过程中抛出了异常

Symfony - 进程运行抛出异常 - 在命令行上执行有效