Archive for the ‘Modulecategory

Nidificació nivell profund massa recursius dependència d'Error PHP

12 de març, 2010

He instal·lat PHP 5.2 en un dels meus ordinadors proves avui i un parell de miques de codi que prèviament treballat bé en la versió 5.1.6 va llançar errors fatals en la nova versió. El missatge d'error era "nius nivell massa profund-dependència recursiu?"i va prendre una mica de temps

de perseguir l'arrel del problema. Aquí és què havia fet malament.

Hi ha dos operadors de comparació en PHP, = = i = = =. En general es coneix que el primer no és massa estrictes amb el tipus, però el segon és. Tan, per exemple

Eco ( = = fals 0 ); // veritable

Eco ( fals = = = 0 ); // fals

– 0 és un nombre enter i un booleà és falsa

El meu problema va sorgir de l'ús no-objectiva mecanografia amb objectes.

$un = nova MyObj();
$b = nova MyObj();
Si( $un = = $b )

Jo no havia considerat 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ó recursiu de totes les propietats de cada objecte, i totes les seves propietats, etc.. fins arribar a tipus de dades bàsiques com cordes i enters.

Si, No obstant això, utilitzem estricta comparació (===), PHP comprovarà si els dos objectes són exactament el mateix objecte, objectes no només amb les mateixes propietats.

classe MyObj
{
públic $p;
}

$un = nova MyObj();
$b = nova MyObj();
$c = MyObj nou();
$un->p = 1;
$b->p = 1;
$c->p = 2;
Eco ( $un = = $c ); // fals
Eco ( $un = = $b ); // veritable
Eco ( $a = = = $b ); // fals

El problema sorgeix si teniu referències circulars en les propietats d'objectes. Tan, per exemple

classe MyObj
{
públic $p;
}
classe OtherObj
{
públic $q;
}

$un = nova MyObj();
$b = nova OtherObj();
$un->p = $b;
$b->q = $a; // la referència circular: $un->p->q = = = $a

$c = MyObj nou();
$d = nova OtherObj();
$c->p = $d;
$d->q = $c;// una altra referència circular: $c->p->q = = = $c

Eco ( $un = = $c ); // Fatal error:
Nidificació nivell massa profund – dependència recursiu?

Per poder comparar $a a $c, PHP ha de comparar les seves propietats. Així que la lògica en PHP va alguna cosa com això: $un = = $c si $a ->p = = $c ->p si $a ->p->q = = $c ->p->q si $a ->p->q->p = = $c ->p->q->p etc.. indefinidament.

PHP 5.1 semblava llis sobre el problema d'alguna manera (probablement després d'un cert nivell de recurrència es torna simplement fals) – i normalment sortia belles. PHP 5.2 correctament produeix l'error fatal de dalt.

Una vegada que sap que el problema, la solució és fàcil – utilitzar l'estricta comparació.

Eco ( $a = = = $c ); // fals (i sense error)

La comparació estricta simplement comprovarà si els dos objectes són a la mateixa ubicació en memòria i així no es veu fins i tot en els valors de les propietats.

NOTA. El mateix problema pot sorgir quan utilitzeu els operadors de comparació negades (ús != = en comptes de !=) i quan utilitzant in_array (Utilitzeu paràmetre tercer de in_array per indicar l'estricta comparació).