ネストされたオブジェクトの複雑な階層があり、すべての子オブジェクト(親クラスにオブジェクトの配列が格納されています)には、親にリンクするプロパティが含まれています。かなり単純で簡単で、実際の問題はありません。階層内の任意のオブジェクトの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
最近、その階層にいくつかの新しい要素を追加しましたが、それらはまったく同じパターンに従っていません。それらは最上位の親のオブジェクトの配列に格納されますが、親ではなく兄弟にそれらをリンクするプロパティが含まれています。ここで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
そのvar_dump()を除いて、コード内の他のすべてが正しく動作します。この質問をするときに例を提供できるように、問題を示すために簡単な例を作成してみました。しかし、短いテストでそれを複製することはできませんでした。私のより複雑なコード内でのみです。
解決策は関係をリファクタリングしてSECONDGEN_2オブジェクトの_children_2配列を適切なSECONDGEN_1親に保持し、親関係を「正しい」ものにすることです...私はすでにこれを開始しています。しかし、私はこのエラーに興味をそそられ、他の誰かがこのエラーに遭遇したのか(そして自分でどのように対処したのか)と思いました。
PHP自己参照コードの制限で、print_r
、var_dump
、var_export
で表示するか、またはin_array
。基本的に、オブジェクトが循環的に参照されている場合、これらの関数が再帰を停止する場所を知る方法はありません。
このバグレポート によると これを再現する の最も簡単な方法は次のとおりです:
$outText = var_export( $GLOBALS, true );
print_r($outText) ;
他のバグレポート メンション それも、いくつかのテストケースで。これがvar_dump
でのみトリガーされる場合は、あまり心配する必要はありません。これがデバッグ目的である場合、xdebugに関するWrikkenの提案は間違いなく2番目です。
==
_ではなく_===
_を使用して再帰オブジェクトを比較する場合にも発生します。実際のオブジェクトインスタンスを比較する必要がある場合は、厳密な比較演算子_===
_を使用します。同じクラス。
簡単な説明:
_$object == $objectToCompareWith
_を使用してオブジェクトを比較する場合、PHPは最初のオブジェクトのすべての属性と値を2番目のオブジェクトと比較しています。この比較は、比較されるオブジェクトのプロパティであるオブジェクトに対して再帰的です。
つまり、両方のオブジェクトがオブジェクトを値として持つ属性を共有する場合、PHPはこれらの属性オブジェクト間で同じ_==
_比較を行います。これらの属性オブジェクトの再帰的(例:自己参照オブジェクト)は、ネストレベルが最大に達するまで比較も再帰的に繰り返されます。
Josh Stuartとmazatworkのコメントで述べたように、in_array()
やarray_search()
などの配列関数を使用する場合、それぞれの_$strict
_パラメーターをtrue
。
時々(ただし、そのような委託に使用される有効な制限があるため、めったにありません)、これが起こり、コードが適切に動作する限り、var_dump
(本番環境ではなくデバッグツール)では対応できません。ただし、それでも必要var_dump
を使用するには、xdebugを実行することを強くお勧めします。この場合、max-depthを設定できますvar_dump
には、文字列ダンプの最大長と子の最大数が表示されます。
私はあなたと同じエラーを受け取りましたが、まったく異なるシナリオでした。他の誰かが私と同じ方法でここに来た場合に備えて、私は答えを投稿しています。
オブジェクトの配列を使用してカスタムソート(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");
それは明らかになった $object->num_estimates
は、数値ではなくオブジェクトを返す場合がありました。常に数値が返されることを確認したら、エラーはなくなりました。
マジックメソッド __ toString を使用して、文字列へのカスタム変換を定義できます。オブジェクトに目を通し、__ toStringを実装するときに再帰を深く掘り下げすぎないようにしてください。忘れないで、誤ってvar_dump、var_export、print_rなどを呼び出してください。
__toStringメソッドを定義すると、次のようにうまく機能します。
echo $ yourObjectHere;
これはうまく機能する私の現在の解決策ですが、var_dump、var_export、print_rを呼び出さないことを忘れないように、何かを保護したいのですが。
多分これは誰かを助ける。
私にとっての解決策は、pcre.recursion_limit
php.ini内。ただし、問題はおそらく自分のコード内にあるため、他の回答を読んだ場合は一時的な回避策になります。