可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
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?".
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.
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).
回答1:
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.
According to this bug report the easiest way to reproduce this is:
$outText = var_export( $GLOBALS, true );
print_r($outText) ;
Other bug reports mention it too, with some more test cases. I'd say that if this is only triggered in var_dump
you shouldn't worry too much about it. I definitely second Wrikken's suggestion about xdebug if this is for debugging purposes.
回答2:
This also arises if you compare recursive objects using ==
instead of ===
If you need to compare actual object instances always 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.
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.
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 $strict
parameter to true
.
Richard Lord: "Nesting level too deep – recursive dependency?"
PHP Manual: "Comparing Objects"
回答3:
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 need var_dump
to work, I can heartily recommend running xdebug, in which you can set max-depth the var_dump
will show, the max-length of a string dump and the maximum amount of children.
回答4:
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:
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_estimates
was occasionally returning an object instead of a number. Once I made sure it was always returning a number then the error went away.
回答5:
You could use the magic method __toString to 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.
Once the __toString method has been defined the following works nicely:
echo $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.
回答6:
Maybe this helps someone.
For me, a solution was to raise pcre.recursion_limit
in 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.