Dlaczego PHP traktuje „0” jako FAŁSZ w kontekście logicznym?
12
„0”, jako ciąg zawierający jeden znak, nie jest czymś intuicyjnie pustym. Dlaczego PHP traktuje to jako FAŁSZ po konwersji na wartość logiczną, w przeciwieństwie do innych języków programowania?
duplikat: stackoverflow.com/questions/523643/… . Tak samo jest zarówno w PHP, jak i javascript, sprawdź odpowiedź poniżej zaakceptowaną odpowiedź.
Walfrat,
5
To dlatego, że PHP dokłada wszelkich starań, aby być tak niespójnym, z samym sobą i każdym innym językiem programowania, jak to możliwe.
David Arno,
2
@DavidArno Przeciwnie, stara się być konsekwentnym ; po uruchomieniu autocastingu ciągów (bardzo przydatne w języku, który często pobiera zmienne z adresów URL lub treści żądań), musisz postępować zgodnie z tą logiką. Jeśli '0'jest traktowany jako 0IN $x + 1, dlaczego nie powinno być również traktowane jak 0i dlatego false, w if ( $x )?
IMSoP,
1
@DavidArno dokładnie;)
linuxunil
1
@DavidArno Myślę, że po rozpoczęciu rzutów stratnych pewna niekonsekwencja jest nieunikniona; konsekwentne rozwiązanie polega na odrzuceniu niektórych rzutów i zaprojektowaniu pozostałych bardzo ostrożnie. Jednak bardzo niewiele popularnych języków zaprojektowano od zera; większość ewoluuje albo z przypadkowo popularnych eksperymentów, albo ze starszych języków o różnych celach i bagażu. Nawet C #, który ma dużo teoretycznego brzmienia, ma pewne dziedzictwo od C, które nigdy nie miało być tak uniwersalne, jak się stało. Snark, jak „chodzenie do przodu, aby być niekonsekwentnym”, jest jak krzyczenie na sędziego podczas meczu sportowego.
IMSoP,
Odpowiedzi:
12
PHP został zaprojektowany (a raczej rozwinięty) do użytku z żądaniami internetowymi, w których często masz do czynienia z ciągami wejściowymi (parametrami URL lub żądaniami POST z formularza w przeglądarce). W związku z tym automatycznie rzutuje ciągi na inne typy.
Prostym przykładem jest to, że '1' + '2'podaje się 3, a nie błąd lub '12„lub inną interpretację. Zgodnie z tą samą logiką ciąg '0'może być używany jako liczba 0.
Tymczasem, podobnie jak wiele języków, PHP traktuje pewne wartości jako „falsy”, gdy są rzutowane na logiczne - które, jak mówisz, są intuicyjnie „puste”. Obejmuje to wartości numeryczne 0, a także pusty ciąg znaków ''i pustą tablicę []. W ifwyrażeniu wyrażenie jest jawnie rzutowane na boolean, więc if ( 0 )jest takie samo jak if ( false ).
Łącząc te dwie rzeczy, otrzymujesz zagadkę: z jednej strony, jak mówisz, '0'jest niepustym łańcuchem; z drugiej strony powiedzieliśmy, że można go używać jako liczby 0, która jest „pusta”. PHP decyduje się traktować „zero-ness” jako ważniejsze niż „rygorystyczność”, dlatego '0'uważa się to za „fałsz”.
W skrócie '0' == 0 == false:; lub(bool)'0' === (bool)(int)'0'
Czy ktoś głosował za moją odpowiedzią tylko dlatego, że odważyłem się obronić PHP i odpowiedzieć na to pytanie innym niż tani i ignorancki żart? A może w mojej odpowiedzi jest coś niedokładnego lub nieprzydatnego, na co chcieliby zwrócić uwagę?
IMSoP,
1
Myślę, że PHP wziął to od Perla, który ma takie samo zachowanie „ "0" jest fałszywe”. W Perlu dosłownie nie ma żadnej widocznej dla użytkownika różnicy między ciągiem "0"a liczbą 0- denerwujące podczas obsługi JSON, ale bardzo intuicyjne podczas obsługi danych tekstowych. Nie jest możliwe, aby liczba 0była falsey bez "0"falsey. PHP i JavaScript pożyczyć tej decyzji projektowych, ale dodać trochę zamieszania poprzez odróżnienie strings / bools / typów numerycznych jednocześnie umożliwiając niejawne konwersje (PHP 0 == "0 foo", 0 == falseale "0 foo" == true: ==nie jest przechodni)
Amon
@amon Tak, Perl stosuje interesujące podejście (prawie) wszystkich operatorów i wbudowanych funkcji, zmuszając operandy do określonego typu, z dodatkowymi operatorami, takimi jak w eqprzypadku równości łańcuchów. Nie "0 foo"chroni to jednak przed nieprzechodnością rzutów stratnych: jest prawdą w kontekście boolowskim, ale równa się 0pod ==. Tak if ( ! $foo ) ..i $false = (1 == 2); if ( $foo == $false ) ... nie dają ten sam rezultat.
Wydaje
Chociaż „0” to 0, gdy jest oceniane jako liczbowe, kiedy używamy łańcucha w kontekście logicznym (na przykład w instrukcji if), nie interesuje nas jego wartość liczbowa. Jeśli chcemy zinterpretować go jako numeryczny, porównalibyśmy go na przykład z pewną liczbą $_POST['id'] == 0, co wyraźnie wyjaśnia, że chcemy traktować dane wejściowe użytkownika jako liczbę.
Michael Tsang
1
@MestreLion Ten przykład dotyczył Perla, a nie PHP. Zasadniczą różnicą, że nie ma oddzielny typ boolean w Perl, więc $falsekończy się zestaw do 0; więc kiedy piszesz $foo == $false, Perl nie wie, że chcesz porównania boolowskiego, i zamiast tego rzuca int. W PHP tak się nie dzieje, ponieważ $falseboolean ma wartość false, więc zmienia się ==na boolean, dając taki sam wynik jak!
IMSoP
3
Zgodnie z dokumentacją PHP na temat booleanów mówi:
Podczas konwersji na wartość logiczną brane są pod uwagę następujące wartości FALSE
...
pusty ciąg, a ciąg „0”
...
Inaczej:
Każda inna wartość jest uważana za PRAWDA (w tym każdy zasób).
Jeśli uruchomisz:
var_dump((bool)"0");
Wydrukuje:
bool (fałsz)
Więc działa zgodnie z oczekiwaniami.
Aby jednoznacznie odpowiedzieć na twoje pytanie:
Jednak w większości przypadków rzutowanie jest niepotrzebne, ponieważ wartość zostanie automatycznie przekonwertowana, jeśli operator, funkcja lub struktura kontrolna wymaga argumentu logicznego.
Oznacza to, że „autocast” PHP rzuca „0” na liczbę całkowitą 0, która jest FALSErównież w strukturze kontrolnej, jak powiedzmy if()instrukcja.
'0'
jest traktowany jako0
IN$x + 1
, dlaczego nie powinno być również traktowane jak0
i dlategofalse
, wif ( $x )
?Odpowiedzi:
PHP został zaprojektowany (a raczej rozwinięty) do użytku z żądaniami internetowymi, w których często masz do czynienia z ciągami wejściowymi (parametrami URL lub żądaniami POST z formularza w przeglądarce). W związku z tym automatycznie rzutuje ciągi na inne typy.
Prostym przykładem jest to, że
'1' + '2'
podaje się3
, a nie błąd lub'12
„lub inną interpretację. Zgodnie z tą samą logiką ciąg'0'
może być używany jako liczba0
.Tymczasem, podobnie jak wiele języków, PHP traktuje pewne wartości jako „falsy”, gdy są rzutowane na logiczne - które, jak mówisz, są intuicyjnie „puste”. Obejmuje to wartości numeryczne
0
, a także pusty ciąg znaków''
i pustą tablicę[]
. Wif
wyrażeniu wyrażenie jest jawnie rzutowane na boolean, więcif ( 0 )
jest takie samo jakif ( false )
.Łącząc te dwie rzeczy, otrzymujesz zagadkę: z jednej strony, jak mówisz,
'0'
jest niepustym łańcuchem; z drugiej strony powiedzieliśmy, że można go używać jako liczby0
, która jest „pusta”. PHP decyduje się traktować „zero-ness” jako ważniejsze niż „rygorystyczność”, dlatego'0'
uważa się to za „fałsz”.W skrócie
'0' == 0 == false
:; lub(bool)'0' === (bool)(int)'0'
źródło
"0"
jest fałszywe”. W Perlu dosłownie nie ma żadnej widocznej dla użytkownika różnicy między ciągiem"0"
a liczbą0
- denerwujące podczas obsługi JSON, ale bardzo intuicyjne podczas obsługi danych tekstowych. Nie jest możliwe, aby liczba0
była falsey bez"0"
falsey. PHP i JavaScript pożyczyć tej decyzji projektowych, ale dodać trochę zamieszania poprzez odróżnienie strings / bools / typów numerycznych jednocześnie umożliwiając niejawne konwersje (PHP0 == "0 foo"
,0 == false
ale"0 foo" == true
:==
nie jest przechodni)eq
przypadku równości łańcuchów. Nie"0 foo"
chroni to jednak przed nieprzechodnością rzutów stratnych: jest prawdą w kontekście boolowskim, ale równa się0
pod==
. Takif ( ! $foo ) ..
i$false = (1 == 2); if ( $foo == $false ) ...
nie dają ten sam rezultat.$_POST['id'] == 0
, co wyraźnie wyjaśnia, że chcemy traktować dane wejściowe użytkownika jako liczbę.$false
kończy się zestaw do0
; więc kiedy piszesz$foo == $false
, Perl nie wie, że chcesz porównania boolowskiego, i zamiast tego rzuca int. W PHP tak się nie dzieje, ponieważ$false
boolean ma wartość false, więc zmienia się==
na boolean, dając taki sam wynik jak!
Zgodnie z dokumentacją PHP na temat booleanów mówi:
Inaczej:
Jeśli uruchomisz:
Wydrukuje:
Więc działa zgodnie z oczekiwaniami.
Aby jednoznacznie odpowiedzieć na twoje pytanie:
Oznacza to, że „autocast” PHP rzuca „0” na liczbę całkowitą 0, która jest
FALSE
również w strukturze kontrolnej, jak powiedzmyif()
instrukcja.źródło