Jeg har installert PHP 5.2 på ett av mine testing datamaskiner i dag, og et par biter av kode som tidligere jobbet fint i versjon 5.1.6 kastet fatal feil i den nye versjonen. Feilmeldingen var "fuglefjell nivået for dypt - rekursiv avhengighet?"Og det tok litt tid
I PHP er det to sammenligningsoperatorer, == Og ===. Det er allment kjent at den første ikke er streng om type, men den andre er. Så, for example
ekko ( false == 0 ); // sant
ekko ( falske === 0 ); // falsk
- 0 er et heltall og falske er en boolsk
Mitt problem oppsto fra med ikke-streng skrive med objekter.
$a = new MyObj();
$b = new MyObj();
hvis( $a == $b )
…
Jeg hadde ikke tenkt på hva jeg gjorde med denne koden. Når man sammenligner to objekter ved hjelp av ikke-streng sammenligningsoperator (==) PHP sammenligner alle egenskapene til objektene, og hvis de samsvarer med de objektene anses å være lik. Hvis de ikke stemmer overens med de er ikke like. I effekt, vi har en rekursiv sammenligning av alle egenskapene til hvert objekt, og alle deres egenskaper, etc.. helt til vi når grunnleggende datatyper som strenger og tall.
If, imidlertid, vi bruker strenge sammenligning (===), PHP vil sjekke om de to objektene er nøyaktig den samme objekt, ikke bare objekter med samme egenskaper.
klasse MyObj
{
offentlige $ p;
}$a = new MyObj();
$b = new MyObj();
$c = new MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
ekko ( $a == $c ); // falsk
ekko ( $a == $b ); // sant
ekko ( $a === $b ); // falsk
Problemet oppstår hvis du har sirkelreferanser i objektene egenskaper. Så, for example
klasse MyObj
{
offentlige $ p;
}
klasse OtherObj
{
offentlige $ q;
}$a = new MyObj();
$b = new OtherObj();
$a->p = $ b;
$b->q = $ en; // sirkulær referanse: $a->p->=== Q $ en$c = new MyObj();
$d = new OtherObj();
$c->p = $ d;
$d->$ Q = c;// annen sirkulær referanse: $c->p->q $ c ===ekko ( $a == $c ); // Fatal feil:
Nesting level too deep – rekursive avhengighet?
For å sammenligne $ a til c $, PHP må sammenligne egenskaper. Så logikken i PHP går noe sånt som dette: $a == $c if $a->p == $c->p if $a->p->q == $c->p->q if $a->p->q->p == $c->p->q->p etc. ubestemt tid.
PHP 5.1 så ut til å glatte over problemet en eller annen måte (sannsynligvis etter et visst nivå av rekursjon den bare tilbake falsk) – og vanligvis dePHPar fungert fint. PHP 5.2 riktig produserer den fatale feilen ovenfor.
Når du vet problemet, løsningen er enkel – bruke strenge sammenligning.
ekko ( $a === $c ); // falsk (og ingen feil)
Den strenge sammenligning vil bare sjekke om de to objektene er på samme sted i minnet og så ikke engang se på verdiene av eiendommene.
NB. Det samme problemet kan oppstå når du bruker eliminert sammenligningsoperatorer (bruk !== Stedet for !=) og når du bruker in_array (Bruk in_array tredje parameter for å indikere strenge sammenligning).
