php 致命错误:嵌套级别太深 - 递归依赖?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3834791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 11:16:15  来源:igfitidea点击:

Fatal error: Nesting level too deep - recursive dependency?

phpooprecursionhierarchical-data

提问by Mark Baker

I have a complex hierarchy of nested objects, with all of the child objects (stored an array of objects in the parent class) containing a property linking back to their parent: fairly simple and straightforward, with no real problems. If I do a var_dump of any object in the hierarchy, I'll get a recursive reference in the dump, exactly as I'd expect.

我有一个复杂的嵌套对象层次结构,所有子对象(在父类中存储了一个对象数组)都包含一个链接回其父对象的属性:相当简单明了,没有真正的问题。如果我对层次结构中的任何对象执行 var_dump,我将在转储中得到一个递归引用,正如我所期望的那样。

FIRSTGEN 
   _children array of objects of type SECONDGEN
      SECONDGEN #1
         _parent object of type FIRSTGEN
         _children array of objects of type THIRDGEN
            THIRDGEN #1
               _parent object of type SECONDGEN
            THIRDGEN #2
               _parent object of type SECONDGEN
      SECONDGEN #2
         _parent object of type FIRSTGEN
         _children array of objects of type THIRDGEN
            THIRDGEN #3
               _parent object of type SECONDGEN

I've recently added some new elements to that hierarchy, and they don't follow quite the same pattern. They are stored in an array of objects in the top-level parent, but contain a property linking them back, not to their parent, but to a sibling. When I do a var_dump now, I get a "Fatal error: Nesting level too deep - recursive dependency?".

我最近向该层次结构添加了一些新元素,但它们遵循的模式并不完全相同。它们存储在顶级父级的对象数组中,但包含将它们链接回的属性,而不是它们的父级,而是链接到同级。当我现在执行 var_dump 时,出现“致命错误:嵌套级别太深 - 递归依赖?”。

FIRSTGEN 
   _children_1 array of objects of type SECONDGEN_1
      SECONDGEN_1 #1
         _parent object of type FIRSTGEN
         _children array of objects of type THIRDGEN
            THIRDGEN #1
               _parent object of type SECONDGEN_1
            THIRDGEN #2
               _parent object of type SECONDGEN_1
      SECONDGEN_1 #2
         _parent object of type FIRSTGEN
         _children array of objects of type THIRDGEN
            THIRDGEN #3
               _parent object of type SECONDGEN_1
   _children_2 array of objects of type SECONDGEN_2
      SECONDGEN_2 #1
         _parent object of type SECONDGEN_1

Everything else within the code works correctly, with the exception of that var_dump(). I've tried creating a simpler example to demonstrate the problem, so that I could provide an example when asking this question; but haven't been able to replicate it in a short test, only within my more complex code.

除了 var_dump() 之外,代码中的其他所有内容都可以正常工作。我尝试创建一个更简单的示例来演示该问题,以便在提出此问题时可以提供一个示例;但无法在简短的测试中复制它,只能在我更复杂的代码中复制它。

I know that the solution is to refactor the relationship so that my _children_2 array of SECONDGEN_2 objects is held in the appropriate SECONDGEN_1 parent, making the parent relationship "correct"... I've already started doing this. However, I'm intrigued by the error, and wondered if anybody else had encountered it (and how you dealt with it yourself).

我知道解决方案是重构关系,以便我的 SECONDGEN_2 对象的 _children_2 数组保存在适当的 SECONDGEN_1 父级中,使父级关系“正确”......我已经开始这样做了。但是,我对这个错误很感兴趣,想知道是否有其他人遇到过它(以及你自己是如何处理的)。

采纳答案by Fanis Hatzidakis

Looks like a PHP limitation in self-referencing code and trying to display it with print_r, var_dump, var_export, or search through it with in_array. Basically there's no way for those functions to know where to stop recursing if an object is referenced cirularly.

看起来像 PHP 在自引用代码中的限制,并试图用print_r, var_dump,显示它var_export,或者用in_array. 基本上,如果循环引用对象,则这些函数无法知道在哪里停止递归。

According to this bug reportthe easiest way to reproduce thisis:

根据此错误报告重现此问题的最简单方法是:

$outText = var_export( $GLOBALS, true );
print_r($outText) ;

Other bug reports mentionit too, with some more test cases. I'd say that if this is only triggered in var_dumpyou shouldn't worry too much about it. I definitely second Wrikken's suggestion about xdebug if this is for debugging purposes.

其他错误报告也提到了它,还有一些测试用例。我会说,如果这只是在var_dump你身上触发,你不应该太担心它。如果这是出于调试目的,我绝对支持 Wrikken 关于 xdebug 的建议。

回答by flu

This also arises if you compare recursive objects using ==instead of ===

如果您使用==而不是比较递归对象,也会出现这种情况===

If you need to compare actual object instancesalways use the strict comparison operator ===as it only compares if the objects refer to the same instance of the same class.

如果您需要比较实际的对象实例,请始终使用严格比较运算符,===因为它仅在对象引用同一类的同一实例时进行比较。

Short explanation:

简短说明:

If you compare objects using $object == $objectToCompareWith, PHP is comparing every attribute and value of the first object with the second. This comparison is recursive over objects which are properties of the objects being compared.

如果使用 比较对象$object == $objectToCompareWith,PHP 会将第一个对象的每个属性和值与第二个对象进行比较。这种比较是对作为被比较对象的属性的对象进行递归的。

That means that if both objects share an attribute with an object as its value, PHP does the same ==comparison between those attribute objects. Now as soon as on of those attribute objects is recursive (e.g. a self referencing object) the comparison recurses down too until the maximum nesting level is reached.

这意味着如果两个对象共享一个属性,并将一个对象作为其值,PHP 会==在这些属性对象之间进行相同的比较。现在,只要这些属性对象中的一个是递归的(例如,自引用对象),比较也会向下递归,直到达到最大嵌套级别。

As stated in the comments by Josh Stuart and mazatwork, strict comparison can be forced when using array functions like in_array()and array_search()by setting their respective $strictparameter to true.

正如 Josh Stuart 和 mazatwork 的评论中所述,在使用像in_array()和这样的数组函数时,可以array_search()通过将它们各自的$strict参数设置为来强制进行严格比较true

Richard Lord: "Nesting level too deep – recursive dependency?"

Richard Lord:“嵌套层次太深——递归依赖?”

PHP Manual: "Comparing Objects"

PHP 手册:“比较对象”

回答by Wrikken

Sometimes (but seldom, as there are limited valid used for such contrustcs) this happens, and as long as your code works properly, I wouldn't give it much thought that a var_dump(a debugging tool, not a production one) cannot cope with it. However, if you still needvar_dumpto work, I can heartily recommend running xdebug, in which you can set max-depth the var_dumpwill show, the max-length of a string dump and the maximum amount of children.

有时(但很少,因为用于此类contrustcs的有效方法有限)会发生这种情况,只要您的代码正常工作,我就不会过多考虑var_dump(调试工具,而不是生产工具)无法应对它。但是,如果您仍然需要var_dump工作,我强烈建议您运行xdebug,在其中您可以设置var_dump将显示的最大深度,字符串转储的最大长度和最大子项数量。

回答by Hymansonkr

I was getting the same error as you but in an entirely different scenario. I'm posting the answer in case anyone else gets here the same way I did.

我遇到了与您相同的错误,但在完全不同的情况下。我正在发布答案,以防其他人以与我相同的方式到达这里。

In the case that you're trying a custom sort (usort)with an array of objects, here's what I had to do:

如果您尝试使用对象数组进行自定义排序(usort),则我必须执行以下操作:

function cmp($a, $b) {
    if($a->num_estimates == $b->num_estimates) return 0;

    return($a->num_estimates < $b->num_estimates) ? -1 : 1;
}
$c = usort(Company::$companies, "cmp");

It turned out that $object->num_estimateswas occasionally returning an object instead of a number. Once I made sure it was always returning a number then the error went away.

事实证明,$object->num_estimates它偶尔会返回一个对象而不是一个数字。一旦我确定它总是返回一个数字,那么错误就消失了。

回答by pduersteler

Maybe this helps someone.

也许这对某人有帮助。

For me, a solution was to raise pcre.recursion_limitin php.ini. It's more of a temporary workaround when you read the other answers, though, as the problem most likely lies inside your own code.

对我来说,一个解决方案是pcre.recursion_limit在 php.ini 中提出。但是,当您阅读其他答案时,这更像是一种临时解决方法,因为问题很可能存在于您自己的代码中。

回答by Paul

You could use the magic method __toStringto define a custom conversion to a string. Look through your object and avoid going too deep through recursions when implementing __toString and everything should be fine. Just never forget and accidentally call var_dump, var_export, print_r etc.

您可以使用魔术方法__toString来定义到字符串的自定义转换。在实现 __toString 时查看您的对象并避免通过递归过深,一切都应该没问题。永远不要忘记并意外调用 var_dump、var_export、print_r 等。

Once the __toString method has been defined the following works nicely:

一旦定义了 __toString 方法,以下就可以很好地工作:

echo $yourObjectHere;

回声 $yourObjectHere;

This is my current solution which works well, but I would still like something to protect me from forgetting not to call var_dump, var_export and print_r.

这是我目前的解决方案,效果很好,但我仍然想要一些东西来保护我不要忘记不要调用 var_dump、var_export 和 print_r。