長すぎる; 読まなかった
このかなり長い投稿でこれを要約します。ある型から別の型への暗黙的な変換が行われます。これを行わない場合は、より厳密===
なキャストまたは明示的なキャストを使用してください。
両方を含む例は、この投稿のさらに下にあります..
型ジャグリングについての詳細は、こちらのマニュアルの関連セクションを参照してください。
PHPインタープリターは私に嘘をついていますか?
そうではありませんが、これは一見すると予想外かもしれませんが、実際には言語の機能 ( type-juggling ) であり、他の状況で非常に使用できることがよくあります。
異なるタイプのオブジェクトを比較する場合、PHP インタープリターは、それらが異なるタイプである場合に共通点を見つける必要があります。当然、暗黙的に一方を他方に変換しようとします。
この場合、文字列"string"を数値に変換しようとします。
以下の行は、質問にあるものと同等です。
if (0 == intval ("string"))
うーん、待って..ええと、何!?
「文字列」から数値への変換は実際には不可能であるため、(言語で指定されているように) 暗黙的な変換が行われ0
ます。
これは、PHP 委員会が決定したため、int に変換される文字列です。
これは主に、そのような暗黙的な変換が数学演算を行うときに役立つためです。
そして、その動作を期待することは、その逆よりもはるかに一般的です。
0
との比較は を比較する0
必要があることはわかってtrue
おり、これがまさに起こっていることです。以下は、質問にあるものと同等ですが、さらに説明するのはより冗長です。
function equal_ ($lhs, $rhs) {
if (gettype ($lhs) == 'integer')
$rhs = intval($rhs);
/* ... */
return $lhs === $rhs;
}
if (equal_ (0, "string")) {
}
でもちょっと.. ちょっと待って!
「スイッチを使用するとき、比較演算子を呼び出すことすらありません。その例では何が起こっているのでしょうか?」
そうではありませんが、インタプリタの内部はswitch-statement を実行するときに行われます。
この問題を回避するには、検索している針、またはラベルとして使用される値を明示的にキャストして、それらが同じ型になるようにする必要があります。
以前のスニペットは、より厳密な比較を可能にするために以下のように記述できます。
switch((string)0) {
case "a":
echo "a";
break;
case "b":
echo "b";
break;
default:
echo "def";
break;
}
この「機能」を使いたくない場合はどうすればよいですか?
PHP4 以降、より厳密な比較演算子があります。===
.
これにより、オペランドの 1 つの暗黙的な変換が許可されなくなります。代わりに、オペランドが同じ型であるかどうかが最初にチェックされます。false を返します。
それらが同じタイプである場合にのみ、実際に2つを比較します。以下の関数は、多くの点で を使用することと同等です===
。
function strict_equal_ ($lhs, $rhs) {
if (gettype ($lhs) != gettype ($rhs))
return false;
return $lhs == $rhs;
}
if (strict_equal_ (0, "string"))
echo "True";
else
echo "False";