He instalado PHP 5.2 en uno de los ordenadores mis pruebas de hoy y un par de trozos de código que previamente trabajó muy bien en la versión 5.1.6 arrojó errores fatales en la nueva versión. El mensaje de error fue "nivel de anidamiento demasiado profundo - recursive dependencia?"Y tomó un poco de tiempo
En PHP existen dos operadores de comparación, == Y ===. Es generalmente conocido que el primero no es estricta sobre el tipo pero el segundo es. Así, por ejemplo
eco ( == falsa 0 ); // verdadero
eco ( === falsa 0 ); // falso
- 0 es un entero y lo falso es un booleano
Mi problema se plantea el uso de escribir no estricta con los objetos.
$a = new MyObj();
$b = new MyObj();
si( $a == $ b )
…
No había pensado en lo que estaba haciendo con este código. Cuando se comparan dos objetos usando el operador de comparación no estricta (==) PHP compara todas las propiedades de los objetos y si coinciden con los objetos se consideran iguales. Si no coinciden no son iguales. En efecto, tenemos una comparación recursiva de todas las propiedades de cada objeto, y todas sus propiedades, etc. hasta llegar a los tipos de datos básicos, como cadenas y números enteros.
Si, sin embargo, usamos una comparación estricta (===), PHP comprobará si los dos objetos son exactamente el mismo objeto, no sólo los objetos con las mismas propiedades.
clase MyObj
{
p $ pública;
}$a = new MyObj();
$b = new MyObj();
$c = new MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
eco ( $a == $ c ); // falso
eco ( $a == $ b ); // verdadero
eco ( $a === $ b ); // falso
El problema se plantea si tiene referencias circulares en sus objetos propiedades. Así, por ejemplo
clase MyObj
{
p $ pública;
}
clase OtherObj
{
pública $ q;
}$a = new MyObj();
$b = new OtherObj();
$a->p = $ b;
$b->q = $a; // la referencia circular: $a->p->q === $a$c = new MyObj();
$d = new OtherObj();
$c->p = $ d;
$d->q = $ c;// otra referencia circular: $c->p->q $ c ===eco ( $a == $ c ); // Fatal error:
El nivel de anidamiento demasiado profundo – dependencia recursiva?
A fin de comparar a $ a $ c, PHP debe comparar sus propiedades. Así que la lógica en PHP es algo como esto: $una c == $ si $ a->p == $c->p si $ a->p->q == $ c->p->q si $ a->p->q-&p == $ c-$c-&gp-p->q->p etc. por tiempo indefinido.
PHP 5.1 parecía suavizar el problema de alguna manera (probablemente después de un cierto nivel de recursividad simplemente devuelve false) – y por lo gePHPal todo salió bien. PHP 5.2 produce correctamente el error fatal por encima de.
Una vez conocido el problema, la solución es fácil – usar la comparación estricta.
eco ( $a === $ c ); // falso (y no hay error)
La comparación estricta simplemente comprobar si los dos objetos están en el mismo lugar en la memoria y por lo tanto ni siquiera mirar a los valores de las propiedades.
N.B. El mismo problema puede surgir cuando se utilizan los operadores de comparación negada (uso !== En lugar de !=) y cuando se utiliza in_array (uso tercer parámetro in_array para indicar comparación estricta).
