3v4l.org

run code in 300+ PHP versions simultaneously
<?php class RecursionDetector { private array $obj_ref_stack = []; private array $arr_ref_stack = []; public function detect(&$val): bool { switch (gettype($val)) { case 'object': $hash = spl_object_hash($val); var_dump($hash); if (isset($this->obj_ref_stack[$hash])) { debug_print_backtrace(); return true; } $this->obj_ref_stack[$hash] = true; $copy = (array) $val; break; case 'array': $ref = ReflectionReference::fromArrayElement([&$var], 0)->getId(); if (isset($this->arr_ref_stack[$ref])) { debug_print_backtrace(); return true; } $this->arr_ref_stack[$ref] = true; $copy = $val; break; default: return false; } $recurse = false; foreach ($copy as $k => $_) { if ($this->detect($copy[$k])) { $recurse = true; break; } } switch (gettype($val)) { case 'object': unset($this->obj_ref_stack[$hash]); break; case 'array': unset($this->arr_ref_stack[$ref]); break; } return $recurse; } } $d = new RecursionDetector(); class X { public array $y = []; } $x = new X(); $r = new ReflectionClass('X'); $z = $r->newLazyProxy(fn() => $x); $x->y[] = [[$z]]; $_ = $z->y; var_dump($x, $z); var_dump($d->detect($x)); var_dump($d->detect($z));
Output for 8.4.1 - 8.4.13
object(X)#2 (1) { ["y"]=> array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> lazy proxy object(X)#5 (1) { ["instance"]=> *RECURSION* } } } } } lazy proxy object(X)#5 (1) { ["instance"]=> object(X)#2 (1) { ["y"]=> array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> *RECURSION* } } } } } string(32) "00000000000000020000000000000000" string(32) "00000000000000050000000000000000" string(32) "00000000000000050000000000000000" #0 /in/Ad9CN(35): RecursionDetector->detect(Object(X)) #1 /in/Ad9CN(35): RecursionDetector->detect(Array) #2 /in/Ad9CN(35): RecursionDetector->detect(Array) #3 /in/Ad9CN(35): RecursionDetector->detect(Array) #4 /in/Ad9CN(35): RecursionDetector->detect(Object(X)) #5 /in/Ad9CN(35): RecursionDetector->detect(Array) #6 /in/Ad9CN(35): RecursionDetector->detect(Array) #7 /in/Ad9CN(35): RecursionDetector->detect(Array) #8 /in/Ad9CN(69): RecursionDetector->detect(Object(X)) bool(true) string(32) "00000000000000050000000000000000" string(32) "00000000000000050000000000000000" #0 /in/Ad9CN(35): RecursionDetector->detect(Object(X)) #1 /in/Ad9CN(35): RecursionDetector->detect(Array) #2 /in/Ad9CN(35): RecursionDetector->detect(Array) #3 /in/Ad9CN(35): RecursionDetector->detect(Array) #4 /in/Ad9CN(70): RecursionDetector->detect(Object(X)) bool(true)
Output for 8.1.32, 8.2.25 - 8.2.29, 8.3.5 - 8.3.26
Fatal error: Uncaught Error: Call to undefined method ReflectionClass::newLazyProxy() in /in/Ad9CN:63 Stack trace: #0 {main} thrown in /in/Ad9CN on line 63
Process exited with code 255.

preferences:
72.03 ms | 409 KiB | 5 Q