Am instalat PHP 5.2 la unul din computerele de testare mea de astăzi şi o pereche de biţi de cod care a lucrat anterior amendă în versiunea 5.1.6 aruncat erori fatale în noua versiune. Mesajul de eroare a fost "la nivel de cuibar prea adânc - recursive dependenţă?"Şi a luat un pic de timp
În PHP există doi operatori de comparaţie, == Şi ===. Este în general cunoscut faptul că primul nu este strict despre tipul, dar a doua este. Astfel, for example
ecou ( == false 0 ); // adevărat
ecou ( === false 0 ); // fals
- 0 este un întreg şi false este un boolean
Problema mea a rezultat din utilizarea dactilografiere non-strictă cu obiecte.
$a = new MyObj();
$b = new MyObj();
dacă( $a == $b )
…
Nu m-am considerat ceea ce am făcut cu acest cod. Atunci când se compară două obiecte folosind operatorul comparaţie non-strictă (==) PHP compară toate proprietăţile de obiecte şi în cazul în care se potrivesc cu obiecte sunt considerate a fi egale. În cazul în care nu se potrivesc acestea nu sunt egale. În vigoare, avem o comparaţie recursivă de toate proprietăţile fiecărui obiect, şi toate proprietăţile lor, etc. până când vom ajunge la tipuri de bază de date ca siruri de caractere şi numere întregi.
If, totuşi, vom folosi comparaţie strictă (===), PHP va verifica dacă cele două obiecte sunt exact acelaşi obiect, nu doar obiecte cu aceleaşi proprietăţi.
clasa MyObj
{
publice $ p;
}$a = new MyObj();
$b = new MyObj();
$c = new MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
ecou ( $a == $c ); // fals
ecou ( $a == $b ); // adevărat
ecou ( $a === $b ); // fals
Problema apare dacă aveţi referinţe circulare în obiectele proprietăţi. Astfel, for example
clasa MyObj
{
publice $ p;
}
clasa OtherObj
{
publice $ q;
}$a = new MyObj();
$b = new OtherObj();
$a->p = $ b;
$b->q = $ a; // circulară de referinţă: $a->p->=== Q $ a$c = new MyObj();
$d = new OtherObj();
$c->w = $ d;
$d->q = $ c;// o altă circulară de referinţă: $c->p->q $ c ===ecou ( $a == $c ); // Eroare fatală:
Nesting level too deep – recursiv dependenţă?
În scopul de a compara la $ $ a c, PHP trebuie să compare proprietăţile lor. Deci, logica în PHP merge ceva de genul asta: $a == $c if $a->p == $c->p if $a->p->q == $c->p->q if $a->p->q->p == $c->p->q->p, etc. pe termen nelimitat.
PHP 5.1 părea să netede peste problema oarecum (probabil după un anumit nivel de recursivitate este pur şi simplu a revenit fals) – şi, de obicei estePHPaborat fin. PHP 5.2 produce în mod corect eroare fatală de mai sus.
Odată ce cunosc problema, Soluţia este uşor – utilizarea comparaţie strictă.
ecou ( $a === $c ); // fals (şi nici o eroare)
Comparaţia stricte va verifica doar dacă cele două obiecte sunt la aceeaşi locaţie în memorie şi aşa nu arata chiar la valorile proprietăţilor.
NB. Aceeaşi problemă poate apărea atunci când se utilizează operatorii negat comparaţie (utilizare !== În loc de !=) şi atunci când se utilizează in_array (parametru in_array utilizare a treia pentru a indica comparaţie strictă).
