Schwerwiegender Fehler: Verschachtelungsebene zu tief – rekursive Abhängigkeit?

Lesezeit: 7 Minuten

Benutzer-Avatar
Markus Bäcker

Ich habe eine komplexe Hierarchie verschachtelter Objekte, wobei alle untergeordneten Objekte (ein Array von Objekten in der übergeordneten Klasse gespeichert) eine Eigenschaft enthalten, die mit ihrem übergeordneten Objekt verknüpft ist: ziemlich einfach und unkompliziert, ohne wirkliche Probleme. Wenn ich einen var_dump eines beliebigen Objekts in der Hierarchie durchführe, erhalte ich eine rekursive Referenz im Dump, genau wie ich es erwartet habe.

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

Ich habe dieser Hierarchie kürzlich einige neue Elemente hinzugefügt, die nicht ganz dem gleichen Muster folgen. Sie werden in einem Array von Objekten im übergeordneten Objekt der obersten Ebene gespeichert, enthalten jedoch eine Eigenschaft, die sie zurückverknüpft, nicht mit ihrem übergeordneten Objekt, sondern mit einem gleichgeordneten Objekt. Wenn ich jetzt einen var_dump durchführe, erhalte ich einen “Schwerwiegenden Fehler: Verschachtelungsebene zu tief – rekursive Abhängigkeit?”.

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

Alles andere im Code funktioniert korrekt, mit Ausnahme von var_dump(). Ich habe versucht, ein einfacheres Beispiel zu erstellen, um das Problem zu demonstrieren, damit ich ein Beispiel geben kann, wenn ich diese Frage stelle. konnte es aber nicht in einem kurzen Test replizieren, nur in meinem komplexeren Code.

Ich weiß, dass die Lösung darin besteht, die Beziehung so umzugestalten, dass mein _children_2-Array von SECONDGEN_2-Objekten im entsprechenden SECONDGEN_1-Elternteil gespeichert wird, wodurch die Elternbeziehung “korrekt” wird … Ich habe bereits damit begonnen. Ich bin jedoch fasziniert von dem Fehler und habe mich gefragt, ob jemand anderes darauf gestoßen ist (und wie Sie selbst damit umgegangen sind).

  • Etwas Code würde helfen, aber wenn ich raten müsste, würde ich sagen, dass Sie unendliche Rekursion haben (weil ich ein Geschwister meines Geschwisters bin).

    – NullUserException

    30. September 2010 um 21:01 Uhr

  • Ich wünschte, ich könnte mit einem einfachen Codeschnipsel reproduzieren, der hier gepostet werden könnte, aber bisher habe ich es nicht geschafft, in 40 Zeilen oder weniger zu replizieren (ich versuche immer noch, etwas zu produzieren); und selbst wenn ich alles Fremde aus meinem Hauptprojekt lösche (wenn ich es reproduzieren kann), sind es immer noch zu viele Hunderte von Zeilen, um es zu posten.

    – Markus Bäcker

    30. September 2010 um 21:06 Uhr

Benutzer-Avatar
Grippe

Dies tritt auch auf, wenn Sie rekursive Objekte mit vergleichen == Anstatt von ===

Wenn Sie tatsächliche Objektinstanzen vergleichen müssen Verwenden Sie immer den strengen Vergleichsoperator === da es nur vergleicht, wenn die Objekte auf dieselbe Instanz derselben Klasse verweisen.

Kurze Erklärung:

Wenn Sie Objekte mit vergleichen $object == $objectToCompareWith, vergleicht PHP jedes Attribut und jeden Wert des ersten Objekts mit dem zweiten. Dieser Vergleich ist rekursiv über Objekte, die Eigenschaften der verglichenen Objekte sind.

Das heißt, wenn beide Objekte ein Attribut mit einem Objekt als Wert teilen, macht PHP dasselbe == Vergleich zwischen diesen Attributobjekten. Sobald eines dieser Attributobjekte rekursiv ist (z. B. ein selbstreferenzierendes Objekt), wird der Vergleich ebenfalls nach unten rekursiv ausgeführt, bis die maximale Verschachtelungsebene erreicht ist.

Wie in den Kommentaren von Josh Stuart und Mazatwork angegeben, kann ein strenger Vergleich erzwungen werden, wenn Array-Funktionen wie verwendet werden in_array() und array_search() durch Einstellung ihrer jeweiligen $strict Parameter zu true.

Richard Lord: „Verschachtelungsebene zu tief – rekursive Abhängigkeit?“

PHP-Handbuch: “Objekte vergleichen”

  • Grippe – du bist mein Held des Tages. So offensichtlich, wenn man es einmal gelesen hat … Danke!

    – kander

    1. Oktober 2013 um 13:58 Uhr

  • Schön! das gilt auch für in_array und Vergleichen einer Anordnung von Objekten.

    – Josh Stuart

    15. Januar 2014 um 8:40 Uhr

  • array_search() hat auch ein $strict-Argument für die Suche in einem Array von Objekten.

    – Mazatarbeit

    20. Oktober 2016 um 14:27 Uhr


  • Achten Sie jedoch darauf, bei der Verwendung keinen losen Vergleich zu verwenden array_search (Anstatt von in_array), da dies das erste Element in verwerfen würde integer– auch indizierte Arrays. Verwenden if (array_search($needle, $haystack, true) !== false) {doSmth();}

    – helve

    11. Juli 2018 um 13:18 Uhr


Sieht aus wie eine PHP-Beschränkung im selbstreferenzierenden Code und versucht, ihn damit anzuzeigen print_r, var_dump, var_exportoder durchsuchen Sie es mit in_array. Grundsätzlich gibt es für diese Funktionen keine Möglichkeit zu wissen, wo die Rekursion beendet werden soll, wenn auf ein Objekt zirkulär verwiesen wird.

Entsprechend dieser Fehlerbericht der einfachste Weg zu dies reproduzieren ist:

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

Andere Fehlerberichte nennen es auch, mit einigen weiteren Testfällen. Ich würde sagen, wenn dies nur ausgelöst wird var_dump da solltest du dir nicht zu viele sorgen machen. Ich unterstütze definitiv Wrikkens Vorschlag zu xdebug, wenn dies zu Debugging-Zwecken dient.

  • Der zweite Fehlerbericht, den Sie erwähnen, ist eine einfache Eltern->Kind->Eltern-Rekursion, die var_dump() keine Probleme bereitet … sie meldet einfach die Rekursion. Es verursacht nicht einmal Probleme mit Eltern->Kind->Enkelkind->Eltern-Rekursion. Ich war jedoch überrascht über den Geschwisterfall … aufgrund des erfolgreichen Umgangs mit den häufigeren Arten von Rekursionen hätte ich erwartet, dass die Geschwisterbeziehung auf die gleiche Weise gefangen wird.

    – Markus Bäcker

    30. September 2010 um 21:22 Uhr


  • Wenn es mit var_export passiert, dann macht es in einigen Fällen, z. B. beim Generieren von CSV, das Debuggen vorhandener Variablen unmöglich, hier wurde eine Problemumgehung angeboten php.net/manual/ru/function.var-export.php Suche nach Schlüsselwörtern – WORKAROUND für Fehler “Verschachtelungsebene zu tief – rekursive Abhängigkeit”

    – Anonym

    15. August 2014 um 14:53 Uhr


Manchmal (aber selten, da es nur begrenzt gültige Verwendungen für solche Konstrukte gibt) passiert dies, und solange Ihr Code richtig funktioniert, würde ich nicht viel darüber nachdenken, dass a var_dump (ein Debugging-Tool, kein Produktionstool) kann damit nicht umgehen. Allerdings, wenn Sie immer noch brauchen var_dump Damit das funktioniert, kann ich wärmstens empfehlen xdebug auszuführen, in dem man die max-Tiefe einstellen kann var_dump zeigt die maximale Länge eines String-Dumps und die maximale Anzahl von Kindern.

  • Ich denke, dies ist einer der Fälle, in denen es meinen Grund für die Geschwisterbeziehung gibt (um eine Methode zum Auflisten aller SECONDGEN_2-Kinder direkt vom FIRSTGEN-Elternteil bereitzustellen), kann genauso einfach durchgeführt werden, indem SECONDGEN_2-Kinder an ihr entsprechendes SECONDGEN_1-Objekt angehängt werden und für die FIRSTGEN-Methode, um die SECONDGEN_1-Objekte zu durchlaufen und dort eine listSECONDGEN_2-Methode aufzurufen und die Listen zusammenzuführen; also nicht wirklich eine gültige Verwendung. Also überarbeite ich es trotzdem.

    – Markus Bäcker

    30. September 2010 um 21:27 Uhr

  • Es fällt mir schwer, die tatsächliche Struktur von Referenzen zu visualisieren, aber es könnte immer sein, dass es in einem ausreichenden Beispiel einen Pfad für PHP gibt, um Knoten zu springen, ohne auf denselben Knoten zu stoßen, bevor er die maximale Verschachtelungsebene erreicht. Wie viele Knoten haben Sie und gibt es einen solchen Pfad?

    – Wrikken

    30. September 2010 um 23:41 Uhr

Benutzer-Avatar
Jacksonkr

Ich habe den gleichen Fehler wie Sie erhalten, aber in einem völlig anderen Szenario. Ich poste die Antwort für den Fall, dass jemand auf die gleiche Weise hierher kommt wie ich.

Für den Fall, dass Sie eine benutzerdefinierte Sortierung versuchen (usorte) mit einer Reihe von Objekten musste ich Folgendes tun:

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

Es stellte sich heraus, dass $object->num_estimates gab gelegentlich ein Objekt anstelle einer Zahl zurück. Nachdem ich sichergestellt hatte, dass immer eine Nummer zurückgegeben wurde, verschwand der Fehler.

Sie könnten die magische Methode anwenden __toString um eine benutzerdefinierte Konvertierung in eine Zeichenfolge zu definieren. Sehen Sie sich Ihr Objekt an und vermeiden Sie es, zu tief durch Rekursionen zu gehen, wenn Sie __toString implementieren, und alles sollte in Ordnung sein. Nur niemals vergessen und versehentlich var_dump, var_export, print_r usw. aufrufen.

Sobald die __toString-Methode definiert wurde, funktioniert Folgendes gut:

Echo $IhrObjektHier;

Dies ist meine aktuelle Lösung, die gut funktioniert, aber ich möchte immer noch etwas, das mich davor schützt, zu vergessen, var_dump, var_export und print_r nicht aufzurufen.

Benutzer-Avatar
pdu

Vielleicht hilft das jemandem.

Für mich war eine Lösung zu erhöhen pcre.recursion_limit in php.ini. Es ist jedoch eher eine vorübergehende Problemumgehung, wenn Sie die anderen Antworten lesen, da das Problem höchstwahrscheinlich in Ihrem eigenen Code liegt.

1100180cookie-checkSchwerwiegender Fehler: Verschachtelungsebene zu tief – rekursive Abhängigkeit?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy