sirve que programar programacion para anidamiento php oop recursion hierarchical-data

php - que - Error fatal: nivel de anidamiento demasiado profundo, ¿dependencia recursiva?



anidamiento programacion (6)

Tengo una compleja jerarquía de objetos anidados, con todos los objetos secundarios (almacenados en una matriz de objetos en la clase principal) que contienen una propiedad que se vincula con su principal: bastante simple y directa, sin problemas reales. Si hago un var_dump de cualquier objeto en la jerarquía, obtendré una referencia recursiva en el volcado, exactamente como lo esperaría.

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

Recientemente he agregado algunos elementos nuevos a esa jerarquía, y no siguen el mismo patrón. Se almacenan en una matriz de objetos en el padre de nivel superior, pero contienen una propiedad que los vincula, no a su padre, sino a un hermano. Cuando hago un var_dump ahora, me sale un "Error fatal: ¿el nivel de anidamiento es demasiado profundo, dependencia recursiva?".

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

Todo lo demás dentro del código funciona correctamente, con la excepción de que var_dump (). He intentado crear un ejemplo más simple para demostrar el problema, de modo que pueda proporcionar un ejemplo al hacer esta pregunta; pero no he podido replicarlo en una prueba corta, solo dentro de mi código más complejo.

Sé que la solución es refactorizar la relación para que mi matriz _children_2 de objetos SECONDGEN_2 se mantenga en el padre SECONDGEN_1 apropiado, haciendo que la relación principal sea "correcta" ... ya comencé a hacer esto. Sin embargo, estoy intrigado por el error y me pregunto si alguien más lo ha encontrado (y cómo lo manejó usted mismo).


Esto también surge si se comparan objetos recursivos usando == lugar de ===

Si necesita comparar instancias de objetos reales, use siempre el operador de comparación estricto === ya que solo compara si los objetos se refieren a la misma instancia de la misma clase.

Breve explicación:

Si compara objetos usando $object == $objectToCompareWith , PHP está comparando cada atributo y valor del primer objeto con el segundo. Esta comparación es recursiva sobre los objetos que son propiedades de los objetos que se comparan.

Eso significa que si ambos objetos comparten un atributo con un objeto como su valor, PHP hace la misma comparación == entre esos objetos de atributo. Ahora, tan pronto como uno de esos objetos de atributo es recursivo (por ejemplo, un objeto de autorreferencia), la comparación recurre también hacia abajo hasta que se alcanza el nivel máximo de anidación.

Como se indica en los comentarios de Josh Stuart y mazatwork, se puede forzar una comparación estricta cuando se usan funciones de matriz como in_array() y array_search() estableciendo su parámetro $strict respectivo en true .

Richard Lord: "Nivel de anidación demasiado profundo, ¿dependencia recursiva?"

Manual de PHP: "Comparando objetos"


A veces (pero rara vez, ya que se usan válidos limitados para tales contrucciones) esto sucede, y mientras su código funcione correctamente, no le daría mucha importancia a que un var_dump (una herramienta de depuración, no uno de producción) no pueda hacer frente con eso. Sin embargo, si todavía necesitas que var_dump funcione, te recomiendo que ejecutes xdebug, en el que puedes establecer la profundidad máxima que mostrará var_dump , la longitud máxima de un volcado de cadenas y la cantidad máxima de hijos.


Estaba recibiendo el mismo error que tú, pero en un escenario completamente diferente. Estoy publicando la respuesta en caso de que alguien más llegue aquí de la misma manera que yo.

En el caso de que intentes una ordenación personalizada (usort) con una variedad de objetos, esto es lo que tuve que hacer:

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");

Resultó que $object->num_estimates ocasionalmente devolvía un objeto en lugar de un número. Una vez que me aseguré de que siempre estaba devolviendo un número, el error desapareció.


Parece una limitación de PHP en el código de autorreferencia y tratar de mostrarlo con print_r , var_dump , var_export , o buscarlo con in_array . Básicamente, no hay forma de que esas funciones sepan dónde detener las repeticiones si se hace referencia circular a un objeto.

De acuerdo con este informe de errores, la forma más fácil de reproducir esto es:

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

Otros informes de errores lo mention también, con algunos casos de prueba más. Diría que si esto solo se activa en var_dump no deberías preocuparte demasiado por ello. Definitivamente estoy de acuerdo con la sugerencia de Wrikken sobre xdebug si esto es para propósitos de depuración.


Podría usar el método mágico __toString para definir una conversión personalizada a una cadena. Mire a través de su objeto y evite profundizar en las recursiones al implementar __ toString y todo debería estar bien. Nunca olvide y llame accidentalmente a var_dump, var_export, print_r etc.

Una vez que se ha definido el método __toString, lo siguiente funciona bien:

echo $ yourObjectHere;

Esta es mi solución actual que funciona bien, pero aún así me gustaría algo para protegerme y evitar que no llame a var_dump, var_export y print_r.


Tal vez esto ayude a alguien.

Para mí, una solución fue aumentar pcre.recursion_limit en php.ini. Sin embargo, es más una solución temporal cuando lee las otras respuestas, ya que el problema probablemente se encuentra dentro de su propio código.