Mam następujący fragment kodu:
$item['price'] = 0;
/* Code to get item information goes in here */
if($item['price'] == 'e') {
$item['price'] = -1;
}
Ma na celu zainicjowanie ceny przedmiotu na 0, a następnie uzyskanie informacji o niej. Jeżeli cena jest oznaczona jako „e”, oznacza to wymianę zamiast sprzedaży, która jest przechowywana w bazie danych jako liczba ujemna.
Istnieje również możliwość pozostawienia ceny jako 0, ponieważ przedmiot jest bonusem lub cena zostanie ustalona w późniejszym momencie.
Ale za każdym razem, gdy cena nie jest ustalona, co pozostawia wartość początkową 0, if
pętla wskazana powyżej jest oceniana jako prawda, a cena jest ustawiana na -1. Oznacza to, że uważa 0 za równe „e”.
Jak można to wyjaśnić?
Gdy cena jest podana jako 0 (po inicjalizacji), zachowanie jest błędne: czasami wartość if jest oceniana jako prawda, czasami jest oceniana jako fałszywa. *
if((string)$item['price'] == 'e')
naprawia dziwne zachowanie. Zobacz stackoverflow.com/a/48912540/1579327 o więcej szczegółówOdpowiedzi:
Robisz,
==
co sortuje dla ciebie typy.0
jest int, więc w tym przypadku będzie rzutować'e'
na int. Który nie jest parsowalny jako jeden i stanie się0
. Ciąg'0e'
stałby się0
i pasowałby!Posługiwać się
===
źródło
Wynika to z tego, jak PHP wykonuje operację
==
porównania, którą operator porównania oznacza:Ponieważ pierwszym operandem jest liczba (
0
), a drugim ciągiem znaków ('e'
), łańcuch jest również konwertowany na liczbę (zobacz także tabelę Porównanie z różnymi typami ). Strona podręcznika dotycząca typu danych łańcuchowych definiuje sposób konwersji ciągu znaków na liczbę :W tym przypadku ciąg jest
'e'
i dlatego zostanie oceniony jako zmiennoprzecinkowy:Ponieważ
'e'
nie zaczyna się od prawidłowych danych liczbowych, przyjmuje postać float0
.źródło
oblicza,
true
ponieważ pierwsza"ABC"
jest konwertowana na liczbę całkowitą i staje się,0
a następnie jest porównywana z0
.Jest to dziwne zachowanie języka PHP: normalnie można by oczekiwać,
0
że zostanie promowany do łańcucha znaków,"0"
a następnie porównany"ABC"
z wynikiemfalse
. Być może dzieje się tak w innych językach, takich jak JavaScript, w przypadku których"ABC" == 0
oceniane jest słabe porównaniefalse
.Wykonanie ścisłego porównania rozwiązuje problem:
ocenia
false
.Ale co, jeśli muszę porównać liczby jako ciągi z liczbami?
ocenia,
false
ponieważ lewy i prawy termin są różnego typu.Właściwie potrzebne jest słabe porównanie bez pułapek związanych z żonglowaniem typu PHP.
Rozwiązaniem jest jawne promowanie terminów do łańcuchów, a następnie porównanie (ścisłe lub słabe już nie ma znaczenia).
jest
true
podczas
jest
false
Zastosowany do oryginalnego kodu:
źródło
Operator == będzie próbował dopasować wartości, nawet jeśli są one różnego typu. Na przykład:
Jeśli potrzebujesz również porównania typów, użyj operatora ===:
źródło
Twoim problemem jest operator podwójnej równości, który przypisze prawy element do typu lewego. Jeśli wolisz, użyj ścisłego.
Wróćmy do twojego kodu (skopiowanego powyżej). W tym przypadku w większości przypadków $ item ['price'] jest liczbą całkowitą (oczywiście z wyjątkiem sytuacji, gdy jest równe e). W związku z tym, zgodnie z prawami PHP, PHP będzie rzutować
"e"
na liczbę całkowitą, co daje wynikint(0)
. (Nie wierzysz mi?<?php $i="e"; echo (int)$i; ?>
).Aby łatwo od tego uciec, użyj operatora potrójnej równości (dokładnego porównania), który sprawdzi typ i nie będzie niejawnie rzutować.
PS: zabawny fakt w PHP:
a == b
nie oznacza tegob == a
. Weź swój przykład i odwróć to:if ("e" == $item['price'])
nigdy nie zostanie spełniony, pod warunkiem, że $ item ['price'] jest zawsze liczbą całkowitą.źródło
W PHP jest dość przydatna metoda sprawdzania poprawności kombinacji „0”, „false”, „off” as == false i „1”, „on”, „true” as == true, która jest często pomijana. Jest to szczególnie przydatne do analizowania argumentów GET / POST:
Nie jest to całkowicie istotne dla tego przypadku użycia, ale biorąc pod uwagę podobieństwo i fakt, że jest to wynik wyszukiwania, który zwykle znajduje, zadając pytanie o walidację (ciąg znaków) „0” jako fałsz, myślałem, że pomoże to innym.
http://www.php.net/manual/en/filter.filters.validate.php
źródło
Powinieneś użyć
===
zamiast==
, ponieważ zwykły operator nie porównuje typów. Zamiast tego podejmie próbę wpisania elementów na maszynie.Tymczasem
===
bierze pod uwagę rodzaj przedmiotów.===
oznacza „równa się”,==
znaczy „eeeeh .. trochę wygląda jak”źródło
if((string)$item['price']=='e'){ $item['price'] = -1; }
===
operatoraMyślę, że najlepiej jest to pokazać na przykładach, które zrobiłem, wpadając w to samo dziwne zachowanie. Zobacz mój przypadek testowy i mam nadzieję, że pomoże ci to lepiej zrozumieć zachowanie:
źródło
Zasadniczo zawsze używaj
===
operatora, aby zagwarantować bezpieczeństwo typu.źródło