Zainstalowałem PHP 5.2 na jednym z moich komputerów testowania dziś i kilka fragmentów kodu, który wcześniej pracował dobrze w wersji 5.1.6 rzucił śmiertelne błędy w nowej wersji. Był komunikat o błędzie "Nesting poziomie zbyt głęboko - zależność rekurencyjną?"I to zajęło trochę czasu
W PHP są dwa porównanie operatorów, == A ===. Jest to powszechnie wiadomo, że po raz pierwszy nie jest straszny, ale o typ drugi. Tak, na przykład
echo ( == false 0 ); // prawdziwy
echo ( === false 0 ); // fałszywy
- 0 jest liczbą całkowitą i fałszywe jest wartością logiczną
Mój problem powstał z wykorzystaniem innych niż z przedmiotów ścisłych wpisując.
$= new myobj();
$b = new myobj();
jeśli( $a == $ b )
…
I nie za to, co robię z tym kodem. W dwóch obiektów przy użyciu innych niż ściśle operator porównania (==) PHP porównuje wszystkie właściwości obiektów i jeśli mecz obiektów powinna być równa. Jeśli nie pasują one nie są równe. W istocie, mamy rekurencyjne porównanie wszystkich właściwości każdego obiektu, i wszystkie ich właściwości, itd.. aż dotrzemy podstawowe typy danych, jak i ciągi liczb całkowitych.
Jeśli, jednak, używamy bezpośrednim porównaniu (===), PHP sprawdza, czy dwa obiekty są dokładnie tego samego obiektu, nie tylko obiekty o tych samych właściwościach.
klasy MyObj
{
publicznych $ p;
}$= new myobj();
$b = new myobj();
$c = new myobj();
$->p = 1;
$b->p = 1;
$c->p = 2;
echo ( $== $ c ); // fałszywy
echo ( $a == $ b ); // prawdziwy
echo ( $=== $ b ); // fałszywy
Problem pojawia się, jeśli odwołania cykliczne w właściwości obiektów. Tak, na przykład
klasy MyObj
{
publicznych $ p;
}
klasy OtherObj
{
publicznych $ q;
}$= new myobj();
$b = new OtherObj();
$->p = $ b;
$b->q = $; // odwołania cyklicznego: $->p->=== Q $$c = new myobj();
$d = new OtherObj();
$c->p = $ d;
$d->q = $ c;// innego odwołania cyklicznego: $c->p->q $ c ===echo ( $== $ c ); // Błąd krytyczny:
Poziom zagnieżdżenia zbyt głęboko – zależność rekurencyjną?
W celu porównania $ a do $ c, PHP musi porównać ich właściwości. Tak więc logika w PHP coś takiego: $== $ c, jeśli $ a->p == $c->p jeśli $ a->p->q == $ c->p->q jeśli $ a->pp == $ c-gt;p == $p->p->q->p itd.. czas nieokreślony.
PHP 5.1 Wydawało złagodzić problem jakoś (prawdopodobnie po pewnym poziomie rekursji po prostu zwróciło false) – i zwykle dobrze się udało. PHP 5.2PHPprawnie tworzy fatalny błąd powyżej.
Znając problem, Rozwiązanie jest łatwe – wykorzystania bezpośrednim porównaniu.
echo ( $=== $ c ); // fałszywy (a nie błąd)
Bezpośrednim porównaniu po prostu sprawdzić, czy dwa obiekty są w tej samej lokalizacji w pamięci, a więc nawet nie patrzeć na wartości nieruchomości.
NB. Ten sam problem może wystąpić przy korzystaniu z operatorów porównania zanegowane (stosowanie !== Zamiast !=) oraz korzystanie z in_array (in_array używać trzeci parametr wskazuje bezpośrednim porównaniu).
