【问题标题】:Self-referencing models cause Maximum function nesting level of x in Laravel 4自引用模型导致 Laravel 4 中 x 的最大函数嵌套级别
【发布时间】:2013-11-11 14:48:57
【问题描述】:

我正在处理一个相当大的 Laravel 项目,并且正在使用存储库。

我有一个用户存储库,它像这样注入它的依赖项:

public function __construct(CartRepository $cartRepo...)

这会导致以下错误:

Maximum function nesting level of '100' reached, aborting!

我认为这是因为 CartRepo 注入了一个 ItemRepo,后者又注入了 UserRepo,导致无限嵌套循环。

我不明白如何解决这个问题,ItemRepo 需要 UserRepo,因为项目与用户相关联?

以前有人遇到过这种情况吗?如果是这样,您是如何解决的?

我知道我可以增加xdebug.max_nesting_level,但即使值为 750,它仍然会抛出错误,我也宁愿修复根本问题,而不是埋葬它。

【问题讨论】:

  • 我的xdebug.max_nesting_level=999999。它很丑,但很有效。
  • 你是使用 App::bind 还是 App::singleton 来绑定你的依赖到容器?
  • 两者都不是,这些都是通过__construct 方法注入的独立存储库
  • 问题似乎是每次注入存储库时您都在重新实例化存储库类,并且使用 App::singleton 将这些绑定到接口将是一个解决方案,因为这将确保它只调用你的存储库 __construct 方法一次。 App::singleton 只实例化你的存储库一次,并在每个请求它的构造中注入相同的实例。

标签: php laravel dependency-injection laravel-4 circular-dependency


【解决方案1】:

你的依赖图中有一个循环:

UserRepo -> CartRepo -> ItemRepo -> UserRepo -> …

你无法解决这个问题。这是一个无限循环,xdebug.max_nesting_level 帮不了你。

我很惊讶 Laravel DI 容器没有抛出明确的异常。

您必须重新考虑服务/存储库之间的依赖关系,可能通过将一些类拆分为更小、耦合更少的对象。


更新:糟糕,我忘记了几个解决方案!

  • Setter 注入

除了在构造函数中注入依赖之外,您还可以将它注入到 setter 中,该 setter 将在构造对象后调用。在伪代码中,它看起来像这样:

$userRepo = new UserRepository();
$cartRepo = new CartRepository($userRepo);
$userRepo->setCartRepo($userRepo);
  • 懒惰注入

我不知道 Laravel 是否支持惰性注入,但这也是一种解决方案:容器将注入一个代理对象而不是实际的依赖项。该代理对象仅在访问时才加载依赖项,因此无需在调用构造函数时构建依赖项。

【讨论】:

  • 使用 Setters 的问题在于(我认为)它使安静的测试变得更加棘手。我看不到任何有关延迟注入的信息,但我认为使用 App::singleton 就可以了。我已提交 an issue to the Laravel Framework 询问让 DI 容器查找这些循环。
  • @TomGreen 是的,我也更喜欢构造函数注入,但在这种情况下没有很多解决方案。如果您的 DI 容器支持,可以尝试延迟注入。
【解决方案2】:

对于那些得到这个答案但仍然有点不确定该怎么做的人,我只是想分享我的解决方案。 Matthieu 的解决方案是正确的,但对于像我这样的初学者来说,它仍然没有给我一个实际解决周期性依赖的具体答案。最后我得出的结论是,我的类太大了,将它们分解成更小的类,即使只有一种方法的类也是答案。例如,如果您有一个包含登录方法和注册方法的用户类,然后是其他一些类,例如使用用户类的登录方法的社交类,并且无论出于何种原因,用户类都依赖于社交类那么我的解决方案是将登录方法移动到它自己的没有任何依赖关系的类中。这样,Social 类现在使用没有任何依赖关系的 Login 类。总的来说,我从大约 3 节课增加到 9 节课,这完全解决了我的问题。我认为这种类型的思维对于非初学者来说是直观的,但如果你不知道你不知道什么,那就很难了。

【讨论】:

    【解决方案3】:

    您的错误的原因可能是 Laravel 上的错误,但我目前正在使用 symfony2,并且 symfony2 做了同样的事情(例如在实体类上)没有问题。无论将您的 php.ini 设置 max_nesting_level (默认为 64)设置为更高的值,或者如果您使用的是 xdebug,请检查 xdebug.max_nesting_level 设置。先试试最后一个建议...

    【讨论】:

    • 谢谢,但我已经尝试过了,即使值为 750 也会引发错误...
    猜你喜欢
    • 2016-08-03
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2016-10-14
    相关资源
    最近更新 更多