PHPをインストールしました 5.2 今日、私のテスト用コンピュータの1つと、以前はバージョンで問題なく動作していたいくつかのコードで 5.1.6 新しいバージョンで致命的なエラーを投げました. エラーメッセージは「ネストレベルが深すぎます – 再帰的依存関係」でした?」と、少し時間がかかりました 問題の根本を突き止める. これが私が間違っていたことです.
PHPには2つの比較演算子があります, == と ===. 一般的に知られているのは、前者はタイプについて厳密ではないが、後者はタイプについて厳格である. そう, 例えば
エコー ( false == 0 ); // 真
エコー ( falseの=== 0 ); // 偽
– 0 は整数で、false はブール値です
私の問題は、オブジェクトで非厳密な型付けを使用することから生じました.
$a = 新しい MyObj();
$b = 新しい MyObj();
もし( $a == $b )
…
このコードで何をしているのか考えていませんでした. 厳密でない比較演算子を使用して 2 つのオブジェクトを比較する場合 (==) PHP はオブジェクトのすべてのプロパティを比較し、それらが一致する場合はオブジェクトが等しいと見なされます. 一致しない場合は、等しくありません. 事実上, 各オブジェクトのすべてのプロパティを再帰的に比較します, そしてそれらのすべての特性, 等. 文字列や整数などの基本的なデータ型に到達するまで.
もし, しかし, 厳密な比較を使用します (===), PHPは、2つのオブジェクトがまったく同じオブジェクトであるかどうかを確認します, 同じプロパティを持つオブジェクトだけではありません.
クラスMyObj
{
パブリック・$p;
}$a = 新しい MyObj();
$b = 新しい MyObj();
$c = 新しい MyObj();
$ある->p = 1;
$b->p = 1;
$c->p = 2;
エコー ( $a == $c ); // 偽
エコー ( $a == $b ); // 真
エコー ( $a === $b ); // 偽
この問題は、オブジェクトのプロパティに循環参照がある場合に発生します. そう, 例えば
クラスMyObj
{
パブリック・$p;
}
クラスOtherObj
{
パブリック・$q;
}$a = 新しい MyObj();
$b = 新しい OtherObj();
$ある->p = $b;
$b->q = $a; // 循環参照: $ある->p->q === $a$c = 新しい MyObj();
$d = 新しい OtherObj();
$c->p = $d;
$d->q = $c;// 別の循環参照: $c->p->q === $cエコー ( $a == $c ); // 致命的なエラー:
ネスティングレベルが深すぎる – 再帰的依存関係?
$a$cと比較するために, PHPはそれらのプロパティを比較する必要があります. したがって、PHPのロジックは次のようになります: $a == $c $a- の場合>p == $c->p $a- の場合>p->q == $c->p->q $a- の場合>p->q->p == $c->p->q->Pなど. 無期限.
PHPの 5.1 どういうわけか問題をスムーズに解決したようです (おそらく、一定レベルの再帰の後、単にfalseを返しました) – そして通常、それはうまくいきました. PHPの 5.2 上記の致命的なエラーを正しく生成します.
問題がわかったら, 解決策は簡単です – 厳密な比較を使用する.
エコー ( $a === $c ); // 偽 (エラーなし)
厳密な比較では、2 つのオブジェクトがメモリ内の同じ場所にあるかどうかがチェックされるため、プロパティの値は確認されません.
N.B.(英語). 否定比較演算子を使用する場合にも、同じ問題が発生する可能性があります (使う !== の代わりに !=) そしてin_array (in_array の 3 番目のパラメーターを使用して、厳密な比較を示します).