【问题标题】:Circular reference detected for service检测到服务的循环参考
【发布时间】:2020-01-21 13:31:16
【问题描述】:

我有一个简单的类,如下所示:

<?php
namespace App\Algorithm;

use App\Dao\MatchDao;
use App\Service\MatchService;

class Calculator {
    private $users;
    private $matchDao;

    function __construct(MatchService $matchService, MatchDao $matchDao) {
        $this->users = $matchService->users;
        $this->matchDao = $matchDao;
    }

    public function hourlyRate() {
        $query = $this->matchDao->getSingleColumn('Payment', 'hourly_rate', 32);
        var_dump($query);
    }
}

但我收到以下错误消息:

检测到服务“App\Algorithm\Calculator”的循环引用, 路径:“App\Algorithm\Calculator -> App\Service\MatchService -> 应用\算法\计算器”。

MatchService.php

<?php
namespace App\Service;

use App\Algorithm\Calculator;
use App\Algorithm\Collection;

class MatchService {
    public $users;
    private $collection;
    private $calculator;

    function __construct(Collection $collection, Calculator $calculator) {
        $this->collection = $collection;
        $this->calculator = $calculator;
    }

    public function getMatch($data) {
        $this->users = $this->collection->getAllUsers($data);
        $this->calculator->hourlyRate();
        return 1;
    }

}

问题是MatchService,但我到底做错了什么?

【问题讨论】:

  • 你能给出 MatchService 的定义吗?
  • 你在构造函数中被依赖注入的东西也依赖注入计算器
  • @aynber 当然,我已经更新了我的问题。
  • @MylesK 这是真的。所以这意味着依赖注入不起作用,我必须创建一个新实例?
  • Calculator 需要MatchService,反之亦然

标签: php symfony symfony4


【解决方案1】:

正如一些人指出的那样,循环依赖来自于您试图将 Calculator 注入 MatchService 并同时将 MatchService 注入 Calculator 的事实。在创建另一个之前无法创建一个。

再深入一点,Calculator 似乎正在使用 MatchService 来获取用户列表。作为第二个问题,计算器试图在 MatchService 生成用户之前获取用户。

这是一种可能的重构:

class Calculator
{
    private $matchDao;

    public function __construct(MatchDao $matchDao)
    {
        $this->matchDao = $matchDao;
    }
    public function getHourlyRate($users) // Added argument
    {
        $query = $this->matchDao->getSingleColumn('Payment', 'hourly_rate', 32);
    }
}
class MatchService
{
    private $collection;
    private $calculator;

    public function __construct(Collection $collection, Calculator $calculator)
    {
        $this->calculator = $calculator;
        $this->collection = $collection;
    }
    public function getMatch($data)
    {
        $users = $this->collection->getAllUsers($data);
        $this->calculator->getHourlyRate($users);
    }
}

从计算器的构造函数中移除 MatchService 解决了循环依赖问题。将 $users 传递给 getHourlyRate 解决了在用户可用之前尝试获取用户的问题。

这当然只是一种可能的解决方案。从您发布的代码中不清楚 Calculator 是否真的需要 $users。

【讨论】:

  • 是的,Calculator 确实需要 $users 并且不仅用于单个方法,而且我在 Calculator 中创建了一个 main 方法,它需要一个参数(就像您的代码一样)并且该 main 方法只会创建一个$this-&gt;users = $users 的属性,以便它对 Calculator 类中的所有其他方法很有用。但是谢谢你的回答。这对我帮助很大!
【解决方案2】:

很明显,您将服务 A 注入到服务 B 中,并且还将服务 B 注入到服务 A 中。 这样做似乎有点不合逻辑,但有时是需要的。 就我而言,我有两个服务:

_MySession -> Symfony Session 的原型

_MyClient -> 负责识别客户端并获取其数据库凭据

我使用 MySession 来存储这些凭据,因此,它将可供整个系统使用,但是,要使用 MyClient 获取这些凭据,我需要将一些信息存储到 MySession .... 看,两个服务需要互相工作...

我开始看到同样的情况

检测到服务的循环引用

刚刚升级到 Symfony 5。而且,sfy5 本身提出了解决方案:

composer require symfony/proxy-manager-bridge

记住服务可以设置为

lazy : true

更多信息Symfony Docs

【讨论】:

    【解决方案3】:

    这通常发生在类相互依赖注入时,因此是循环引用。

    给定你上面的例子,你的类MatchService注入CollectionCalculator。其中之一(假设计算器作为集合可能是一个学说类)依赖注入您的MatchService

    这是我想象的你的课程是这样的:

    class MatchService 
    {
        public $users;
        private $collection;
        private $calculator;
    
        public function __construct(Collection $collection, Calculator $calculator) {
            $this->collection = $collection;
            $this->calculator = $calculator;
        }
    }
    
    class Calculator
    {
        private $matchService;
    
        public function __construct(MatchService $matchService)
        {
            $this->matchService = $matchService;
        }
    }
    

    你有几个选择:

    • 更多服务,更少依赖
    • 使用静力学

    我们很难为您解决问题,因为这取决于您如何构建应用程序。

    【讨论】:

    • 贴出的代码实际上非常清楚地显示了循环依赖。不确定在这种情况下通用 foo bar 答案有多大用处。
    • 我的代码示例应该显示循环引用
    • 当然,但是为什么不显示实际的循环引用而不是 foo 和 bar(甚至是苹果和橘子)?并建议静力学作为一种可能的解决方案?嗯。
    • 我已经更新了我的答案以反映他的代码,感谢您的建议。静态可以解决问题,但实际上是他设计应用程序的方式,所以你没有很多方法可以解决它。
    • 我并不是真的要骚扰你,我知道我们应该友善,但我真的不知道你想用这个答案来完成什么。这当然不是建议的修复。无论如何,祝你有一个有用的一天。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2018-04-14
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多