PHP Napaka Pri gnezdenju Ravni Pregloboko reurzivno odvisnost

12. marec, 2010 z admin pusti odgovor »

Sem namestil PHP 5.2 na enem od mojih testnih računalnikov danes in nekaj bitov kode, ki je prej delovala v redu v različici 5.1.6 vrgel usodne napake v novi različici. Sporočilo o napaki je bilo »Nivo gnezdanja pregloboko – reurzivna odvisnost?" in je trajalo nekaj časa za sledenje korenu težave. To sem naredil narobe..

V PHP obstajata dva operaterja za primerjavo, == in ===. Na splošno je znano, da prvi ni strog glede tipa, drugi pa je. Tako, na primer

odmev ( false == 0 ); // Res

odmev ( false === 0 ); // napačno

– 0 je vse število in false je boolean

Moja težava je skotila z uporabo nestrožnega tipkanja z predmeti.

$a = nov MyObj();
$b = nov MyObj();
če( $a == $b )

Nisem preučiti, kaj počnem s to kodo.. Pri primerjanju dveh predmetov z uporabo nestrožnega operatorja za primerjavo (==) PHP primerja vse lastnosti predmetov in če se ujemajo s predmeti, se zdijo enaki. Če se ne ujemajo, niso enaki.. V veljavi, imamo reurzivno primerjavo vseh lastnosti vsakega predmeta, in vse njihove lastnosti, itd. dokler ne dosežemo osnovnih podatkovnih tipov, kot so nizi in splošna.

Če, Vendar pa, uporabljamo strogo primerjavo (===), PHP bo preveril, ali sta ti predmeti popolnoma isti predmet, ne le predmeti z enakimi lastnostmi.

razred MyObj
{
javni $p;
}

$a = nov MyObj();
$b = nov MyObj();
$c = nov MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
odmev ( $a == $c ); // napačno
odmev ( $a == $b ); // Res
odmev ( $a === $b ); // napačno

Težava se pojavi, če imate krožne sklice v lastnostih predmetov. Tako, na primer

razred MyObj
{
javni $p;
}
razred DrugoObj
{
javnih $q;
}

$a = nov MyObj();
$b = novo DrugoObj();
$a->p = $b;
$b->q = $a; // krožno sklicevanje: $a->p->q === $a

$c = nov MyObj();
$d = novo DrugoObj();
$c->p = $d;
$d->q = $c;// drugo krožno sklicevanje: $c->p->q === $c

odmev ( $a == $c ); // Usodna napaka:
Nivo gnezdanja pregloboko – reurzivna odvisnost?

Za primerjavo $a $c, PHP mora primerjati svoje lastnosti. Torej logika v PHP gre nekaj takega: $a == $c če $a->p == $c->p, če $a->p->q == $c->p->q če $a->p->q->p == $c->p->q->p itd.. Nedogled.

PHP 5.1 zdelo, da gladko čez problem nekako (verjetno po določeni stopnji ponovitve je preprosto vrnil napačno) – in ponavadi se je dobro izšlo. PHP 5.2 pravilno povzroči usodno napako zgoraj.

Ko enkrat zavleciš problem, rešitev je enostavna – uporaba stroge primerjave.

odmev ( $a === $c ); // napačno (in ni napake)

Stroga primerjava bo preprosto preverila, ali sta predmeti na istem mestu v pomnilniku in tako niti ne gleda vrednosti lastnosti.

N.B. Enak problem se lahko pojavijo pri uporabi negatenih operaterjev primerjave (uporabiti !== namesto !=) in pri uporabi in_array (tretji parameter in_array, da se navede stroga primerjava).

Oglas

pusti odgovor

Morate biti prijavljeni za objavo komentarjev.