PHPがブールコンテキストで「0」をFALSEとして処理する理由


12

「0」は、1文字を含む文字列として、直感的には空ではありません。他のプログラミング言語とは異なり、PHPはブール値に変換されたときにFALSEとして処理するのはなぜですか?


2
:の複製stackoverflow.com/questions/523643/...。PHPとjavascriptの両方で同じです。以下の回答を受け入れてください。
ウォルフラット16

5
それは、PHP自体と他のすべてのプログラミング言語の両方で、可能な限り一貫性のないものになるように、PHPが非常に長くなるためです。
デビッドアルノ

2
@DavidArnoそれどころか、一貫性を保つために最善を尽くしてます。文字列のオートキャスティングを開始したら(言語やURLからvarを取得することが多い言語では非常に便利です)、そのロジックに従う必要があります。場合'0'として扱われる0$x + 1、なぜそれとしても扱われるべきではない0、したがってfalse、でif ( $x )
IMSoP 16

1
@DavidArno正確に;)
linuxunil

1
@DavidArno損失のあるキャストの実行を開始すると、ある程度の矛盾が避けられないと思います。一貫したソリューションには、一部のキャストを拒否し、残りを非常に慎重に設計することが含まれます。ただし、ゼロから設計された一般的な言語はほとんどありません。ほとんどは、偶然人気のある実験から、または異なる目的と手荷物を持つ古い言語から進化します。健全な理論設計を多く備えたC#でさえ、Cからの遺産をいくつか持っています。「一貫性を保つために最大限の努力をする」というようなスナークは、スポーツの試合でrefで叫ぶようなものです。
IMSoP 16

回答:


12

PHPは、文字列入力(URLパラメーター、またはブラウザー内のフォームからのPOSTリクエスト)を頻繁に処理するWebリクエストで使用するために設計(または、むしろ進化)しました。そのため、文字列を他の型に自動的にキャストします。

この単純な例では、ということです'1' + '2'与え3、エラーではなく、または'12」、または他のいくつかの解釈を。同じロジックにより、文字列'0'を数値として使用できます0

一方、多くの言語と同様に、PHPはブール値にキャストするときに特定の値を「偽」として扱います。これは、直感的に「空」の値です。これには0、空の文字列''と空の配列だけでなく、数値も含まれます[]ifステートメント、式は明示的に、ブール値にキャストされたif ( 0 )と同じですif ( false )

これら2つのことをまとめると、難問が生じます。一方で、あなたが言うの'0'は空でない文字列です。一方、0「空」の数値として使用できると述べました。PHPは、'0'「ゼロネス」を「ストリングネス」よりも重要なものとして扱うことを選択しているため、「偽」と見なされます。

要するに:'0' == 0 == false; または(bool)'0' === (bool)(int)'0'


PHPを守り、安価で無知な冗談以外の何かで質問に答えようと思ったからといって、誰かが私の答えを否定しましたか?それとも、彼らが指摘したい私の答えには不正確または役に立たない何かがありますか?
IMSoP 16

1
PHPは、これを同じ「"0" 偽」の振る舞いを持つPerlから取ったと思います。Perlでは、文字列"0"と数字の間に文字通りユーザーが目に見える違いはありません0。JSONを処理するときは迷惑ですが、テキストデータを処理するときは非常に直感的です。その場合0、文字列も偽でなくて数字を偽にすることは不可能"0"です。PHPとJavaScriptは、この設計上の決定を借り、それでも暗黙の変換を可能にしながら、文字列/ bools /数値型を区別することによって、いくつかの混乱を追加します(PHP: 、0 == "0 foo"0 == falseしかし"0 foo" == true==推移されていません)
アモン

@amonはい、Perlは(ほぼ)すべての演算子と組み込み関数の興味深いアプローチを取り、オペランドを特定の型に強制しますeq。しかし、これは不可逆的なキャストの非推移性からそれを救いません:"0 foo"ブールコンテキストでは真実ですが、0under と等しくなり==ます。だから、if ( ! $foo ) ..$false = (1 == 2); if ( $foo == $false ) ... 同じ結果を与えることはありません。私は言語は一貫し、これを扱うことができ、「ブール平等」オペレータ...不足していると思います
IMSoP

「0」は数値として評価されると0ですが、ブールコンテキストで文字列を使用する場合(ifステートメントなど)、その数値には関心がありません。数値として解釈したい場合は、たとえば、$_POST['id'] == 0などの数値と比較します。これにより、ユーザー入力を数値として扱いたいという意図が明確になります。
マイケルツァン

1
@MestreLionその例は、PHPではなくPerlのものです。重要な違いは、Perlには別個のブール型がないため、最終的$falseには0;に設定されることです。そのため、を記述したときに$foo == $false、Perlはブール値の比較が必要であることを知らず、代わりにintにキャストします。PHPでは、$falseブール値がfalseであるため、これは発生しません。==ブール値にキャストすると、同じ結果が得られます!
-IMSoP

3

booleanに関するPHPドキュメントによると、次のように書かれています。

ブール値に変換する場合、次の値が考慮されFALSE
ます...
空の文字列、および文字列 "0"
...

さもないと:

他のすべての値はTRUE(リソースを含む)と見なされます。

実行する場合:

var_dump((bool) "0");

印刷されます:

bool(false)

期待通りに機能しています。


質問に明示的に回答するには:

ただし、ほとんどの場合、キャストは不要です。演算子、関数、または制御構造がブール引数を必要とする場合、値は自動的に変換されるためです。

これは、PHPの「オートキャスト」が「0」を整数0にキャストすることを意味します。これはFALSEif()ステートメントなどの制御構造でも同様です。


明示的なキャストの必要性ではなく、ブール値に変換されたときに「0」をFALSEとして扱う設計決定の理論的根拠を知りたいと思います。
マイケルツァン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.