Έχω εγκαταστήσει την PHP 5.2 σε κάποιον από τους υπολογιστές δοκιμών μου σήμερα και ένα ζευγάρι από τα κομμάτια του κώδικα που εργάστηκε κατά το παρελθόν πρόστιμο στην έκδοση 5.1.6 έριξε μοιραία λάθη στην νέα έκδοση. Το μήνυμα σφάλματος ήταν «καταφύγιο επίπεδο πάρα πολύ βαθιά - recursive εξάρτηση?»Και πήρε λίγο χρόνο
Στην PHP υπάρχουν δύο χειριστές σύγκριση, == Και ===. Είναι γενικά γνωστό ότι η πρώτη δεν είναι αυστηρά όσον αφορά τον τύπο, αλλά το δεύτερο είναι. Έτσι, για παράδειγμα
ηχώ ( ψευδή == 0 ); // αλήθεια
ηχώ ( ψευδή === 0 ); // ψευδής
- 0 είναι ένας ακέραιος και ψευδής είναι μια boolean
Το πρόβλημά μου προέκυψε από τη χρήση μη αυστηρή τυποποίηση με αντικείμενα.
$α = νέα MyObj();
$β = νέα MyObj();
αν( $a == $ b )
…
Δεν είχε εξετάσει τι έκανα με αυτό τον κωδικό. Κατά τη σύγκριση των δύο αντικείμενα που χρησιμοποιούν τη μη αυστηρή φορέα σύγκριση (==) PHP συγκρίνει όλες τις ιδιότητες των αντικειμένων και αν ταιριάζει με τα αντικείμενα που θεωρούνται ότι είναι ίσο. Αν δεν ταιριάζουν, δεν είναι ίσοι. Στην πραγματικότητα, έχουμε μια αναδρομική σύγκριση όλων των ιδιοτήτων του κάθε αντικειμένου, και όλες τις ιδιότητές τους, κλπ.. μέχρι να φτάσουμε βασικοί τύποι δεδομένων, όπως strings και ακέραιοι.
Αν, ωστόσο, χρησιμοποιούμε αυστηρή σύγκριση (===), PHP θα ελέγξει αν τα δύο αντικείμενα είναι ακριβώς το ίδιο αντικείμενο, δεν είναι μόνο τα αντικείμενα με τις ίδιες ιδιότητες.
τάξη MyObj
{
δημόσια $ p;
}$α = νέα MyObj();
$β = νέα MyObj();
$γ = νέα MyObj();
$α->p = 1;
$β->p = 1;
$γ->p = 2;
ηχώ ( $a == $ c ); // ψευδής
ηχώ ( $a == $ b ); // αλήθεια
ηχώ ( $ένα === $ b ); // ψευδής
Το πρόβλημα ανακύπτει αν έχετε κυκλικές αναφορές σε αντικείμενα που σας ιδιότητες. Έτσι, για παράδειγμα
τάξη MyObj
{
δημόσια $ p;
}
τάξη OtherObj
{
δημόσια $ q;
}$α = νέα MyObj();
$β = νέα OtherObj();
$α->p = $ b;
$β->q = $ a; // η κυκλική αναφορά: $α->p->=== Q $ a$γ = νέα MyObj();
$d = νέα OtherObj();
$γ->p = $ d;
$δ->q = $ c;// μια άλλη κυκλική αναφορά: $γ->p->q $ c ===ηχώ ( $a == $ c ); // Μοιραίο λάθος:
Ένθεση επίπεδο πάρα πολύ βαθιά – recursive εξάρτηση?
Για να συγκρίνετε $ a και $ c, PHP πρέπει να συγκρίνει τις περιουσίες τους. Έτσι, η λογική στην PHP πάει κάπως έτσι: $a == $ c $ αν α->σ. == $ c->σ. αν η $ a->p->q == $ c->p->q αν η $ a->p->Q->σ. == $ c->p->Q->p κλπ. επ 'αόριστον.
PHP 5.1 φαινόταν να λειάνει πέρα από το πρόβλημα με κάποιο τρόπο (πιθανότατα μετά από ένα ορισμένο επίπεδο αναδρομής απλά επιστρέφει false) – και συνήθως επέλυσε πρόστιμο. PHP 5.2 σωστά παράγει το μοιραίο λάθος παραπάνω.
Μόλις ξέρετε το πρόβλημα, η λύση είναι εύκολη – χρήση αυστηρή σύγκριση.
ηχώ ( $$ a === γ ); // ψευδής (και δεν υπέπεσε σε πλάνη)
Η αυστηρή σύγκριση απλά θα ελέγξει αν τα δύο αντικείμενα που βρίσκονται στην ίδια θέση στη μνήμη και έτσι δεν κάνει ούτε μια ματιά στις τιμές των ακινήτων.
Σημείωση:. Το ίδιο πρόβλημα μπορεί να προκύψει κατά τη χρήση του αναιρείται φορείς σύγκριση (χρήση !== Αντί για !=) και όταν χρησιμοποιούν in_array (τρίτη παράμετρο in_array χρησιμοποιούν για να αναφέρουν αυστηρή σύγκριση).
