Ég hef sett upp PHP 5.2 á einni af prófunartölvunum mínum í dag og nokkrum bitum af kóða sem áður virkaði fínt í útgáfu 5.1.6 kastaði banvænum villum í nýju útgáfunni. Villuboðin voru "Hreiðurstig of djúpt – endurkvæm ósjálfstæði?" og það tók smá tíma að hafa uppi á rót vandans. Hér er það sem ég hafði gert rangt.
Í PHP eru tveir samanburðaraðilar, == og ===. Það er almennt vitað að sá fyrri er ekki strangur um gerð en sá síðari er. Svo, Til dæmis
bergmál ( rangt == 0 ); // sannur
bergmál ( ósatt === 0 ); // falskur
– 0 er heiltala og ósatt er boolean
Vandamálið mitt kom upp af því að nota ekki stranga vélritun með hlutum.
$a = nýr MyObj();
$b = nýr MyObj();
ef( $a == $b )
…
Ég hafði ekki íhugað hvað ég var að gera með þessum kóða. Þegar tveir hlutir eru bornir saman með því að nota ósamræmda samanburðaraðilann (==) PHP ber saman alla eiginleika hlutanna og ef þeir passa við hlutina eru taldir vera jafnir. Ef þeir passa ekki saman eru þeir ekki jafnir. Í gildi, við höfum endurkvæman samanburð á öllum eiginleikum hvers hlutar, og allar eignir þeirra, o.s.frv. þar til við náum grunngagnagerðum eins og strengjum og heiltölum.
Ef, hins vegar, við notum strangan samanburð (===), PHP mun athuga hvort hlutirnir tveir séu nákvæmlega sami hluturinn, ekki bara hlutir með sömu eiginleika.
flokkur MyObj
{
opinber $p;
}$a = nýr MyObj();
$b = nýr MyObj();
$c = nýr MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
bergmál ( $a == $c ); // falskur
bergmál ( $a == $b ); // sannur
bergmál ( $a === $b ); // falskur
Vandamálið kemur upp ef þú ert með hringlaga tilvísanir í eiginleika hlutanna þinna. Svo, Til dæmis
flokkur MyObj
{
opinber $p;
}
flokkur OtherObj
{
opinber $q;
}$a = nýr MyObj();
$b = nýr OtherObj();
$a->p = $b;
$b->q = $a; // hringlaga tilvísunin: $a->p->q === $a$c = nýr MyObj();
$d = nýr OtherObj();
$c->p = $d;
$d->q = $c;// önnur hringlaga tilvísun: $c->p->q === $cbergmál ( $a == $c ); // Banvæn villa:
Hreiðurstig of djúpt – endurkvæm ósjálfstæði?
Til að bera $a saman við $c, PHP verður að bera saman eiginleika þeirra. Þannig að rökfræðin í PHP fer eitthvað svona: $a == $c ef $a->p == $c->p ef $a->p->q == $c->p->q ef $a->p->q->p == $c->p->q->p osfrv.. Endalaust.
PHP 5.1 virtist slétta yfir vandamálið einhvern veginn (líklega eftir ákveðinn samdrátt skilaði það einfaldlega röngu) – og yfirleitt gekk þetta ágætlega. PHP 5.2 rétt framleiðir banvæna villu hér að ofan.
Þegar þú veist vandamálið, lausnin er auðveld – notaðu strangan samanburð.
bergmál ( $a === $c ); // falskur (og engin villa)
Strangur samanburður mun einfaldlega athuga hvort hlutirnir tveir séu á sama stað í minni og lítur því ekki einu sinni á gildi eiginleikanna.
N.B.B.. Sama vandamál getur komið upp þegar notaðir eru neituðu samanburðaraðilarnir (nota !== í stað !=) og þegar in_array er notað (notaðu þriðju breytu in_array til að gefa til kynna strangan samanburð).