He instal lat PHP 5.2 en un dels ordinadors meus proves d'avui i un parell de trossos de codi que prèviament va treballar molt bé en la versió 5.1.6 va llançar errors fatals en la nova versió. El missatge d'error va ser "nivell de anidament massa profund - recursive dependència?"I va prendre una mica de temps
A PHP hi ha dos operadors de comparació, == I ===. És generalment conegut que el primer no és estricta sobre el tipus però el segon és. Així, for example
ressò ( == Falsa 0 ); // veritable
ressò ( === Falsa 0 ); // fals
- 0 és un enter i la falsedat és un booleà
El meu problema es planteja l'ús d'escriure no estricta amb els objectes.
$a = new MyObj();
$b = new MyObj();
si( $a == $b )
…
No hi havia pensat en el que estava fent amb aquest codi. Quan es comparen dos objectes utilitzant l'operador de comparació no estricta (==) PHP compara totes les propietats dels objectes i si coincideixen amb els objectes es consideren iguals. Si no coincideixen no són iguals. En efecte, tenim una comparació recursiva de totes les propietats de cada objecte, i totes les seves propietats, etc. fins arribar als tipus de dades bàsiques, com cadenes i números enters.
If, però, fem servir una comparació estricta (===), PHP comprovarà si els dos objectes són exactament el mateix objecte, no només els objectes amb les mateixes propietats.
classe MyObj
{
p $ pública;
}$a = new MyObj();
$b = new MyObj();
$c = new MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
ressò ( $a == $c ); // fals
ressò ( $a == $b ); // veritable
ressò ( $a === $b ); // fals
El problema es planteja si té referències circulars en els seus objectes propietats. Així, for example
classe MyObj
{
p $ pública;
}
classe OtherObj
{
pública $ q;
}$a = new MyObj();
$b = new OtherObj();
$a->p = $ b;
$b->q = $ a; // la referència circular: $a->p->q === $ a$c = new MyObj();
$d = new OtherObj();
$c->p = $ d;
$d->q = $ c;// altra referència circular: $c->p->q $ c ===ressò ( $a == $c ); // Fatal error:
Implantació nivell massa profund – dependència recursiva?
Per tal de comparar a $ a $ c, PHP ha de comparar les seves propietats. Així que la lògica en PHP és una cosa com això: $a == $c if $a->p == $c->p if $a->p->q == $c->p->q if $a->p->q->p == $c->p->q->p etc. per temps indefinit.
PHP 5.1 semblava suavitzar el problema d'alguna manera (probablement després d'un cert nivell de recursivitat simplement retorna false) – i en general va PHPtir bé. PHP 5.2 produeix correctament l'error greu per sobre de.
Un cop conegut el problema, la solució és fàcil – utilitzar una comparació estricta.
ressò ( $a === $c ); // fals (i cap error)
La comparació estricta simplement comprovar si els dos objectes estan en el mateix lloc en memòria i així ni tan sols mirar els valors de les propietats.
NB. El mateix problema pot sorgir quan s'utilitzen els operadors de comparació negada (ús !== En lloc de !=) i quan s'utilitza in_array (in_array tercer paràmetre per indicar l'ús d'una comparació estricta).
