web-dev-qa-db-ja.com

なぜPHPは0が文字列に等しいと見なしますか?

私は次のコードを持っています:

$item['price'] = 0;
/*code to get item information goes in here*/
if($item['price'] == 'e') {
    $item['price'] = -1;
}

アイテムの価格を0に初期化してから、その情報を取得することを目的としています。価格が「e」として通知された場合、それは売りではなく交換を意味し、負の数としてデータベースに保存されます。

また、アイテムがボーナスであるか、価格が後から設定されるため、価格を0のままにする可能性もあります。

ただし、価格が設定されておらず、初期値が0の場合、上記のifループはtrueと評価され、価格は-1に設定されます。つまり、0は「e」に等しいと見なされます。

これはどのように説明できますか?

編集:価格が0(初期化後)として提供されると、動作が不安定になります。ifがtrueと評価される場合もあれば、falseと評価される場合もあります。

101

あなたはあなたのために型を整理する==をしています。

0はintであるため、この場合は'e'をintにキャストします。これは1つとして解析できず、0になります。文字列'0e'0になり、一致します!

===を使用します

101
Nanne

これは、PHPが ==比較演算子 が示す比較演算を行う方法によるものです。

数値を文字列と比較する場合、または比較に数値文字列が含まれる場合、各文字列は数値に変換され、数値的に比較が実行されます。 […]比較が===または!==の場合、タイプと値の比較を伴うため、タイプ変換は行われません。

最初のオペランドが数値(0)で、2番目のオペランドが文字列('e')であるため、文字列も数値に変換されます( tableさまざまなタイプとの比較 )。文字列データ型のマニュアルページでは、 文字列から数値への変換 の実行方法が定義されています。

文字列が数値コンテキストで評価される場合、結果の値とタイプは次のように決定されます。

文字列に「.」、「e」、または「E」のいずれの文字も含まれておらず、数値が整数型の制限(PHP_INT_MAX)、文字列は整数として評価されます。それ以外の場合はすべて、floatとして評価されます。

この場合、文字列は'e'であるため、floatとして評価されます。

値は、文字列の最初の部分で指定されます。文字列が有効な数値データで始まる場合、これが使用される値になります。それ以外の場合、値は0(ゼロ)になります。有効な数値データは、オプションの符号と、それに続く1つ以上の数字(オプションで小数点を含む)、それに続くオプションの指数です。指数は、「e」または「E」の後に1つ以上の数字が続きます。

'e'は有効な数値データで始まっていないため、float 0と評価されます。

46
Gumbo
"ABC" == 0

first"ABC"は整数に変換されて0thenになり、0と比較されるため、trueを評価します。

これは、PHP言語:)のoddの動作です。通常、0がストリング"0"にプロモートされ、その後"ABC"と比較されて結果falseになることが期待されます。おそらく、これは、弱い比較"ABC" == 0falseを評価するJavaScriptのような他の言語で起こることです。

厳密な比較を行うと問題が解決します。

"ABC" === 0

falseを評価します。

しかし、数字と文字列として数字を比較する必要がある場合はどうなりますか?

"123" === 123

左項と右項のタイプが異なるため、falseを評価します。

実際に必要なのは、PHP type juggling。の落とし穴のない弱い比較です。

解決策は、用語を明示的に文字列に昇格させてから比較を行うことです(厳密か弱いかは関係ありません)。

(string)"123" === (string)123

true

ながら

(string)"123" === (string)0

false


元のコードに適用:

$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -1;
}
16
Paolo

あなたの問題は二重等号演算子です。これは、右のメンバーを左のタイプに型キャストします。必要に応じて、strictを使用します。

if($item['price'] == 'e') {
    $item['price'] = -1;
}

コードに戻りましょう(上記のコピー)。この場合、ほとんどの場合、$ item ['price']は整数です(明らかにeと等しい場合を除きます)。そのため、PHPの法律では、PHPは"e"を整数に型キャストし、int(0)を生成します(信じられない?<?php $i="e"; echo (int)$i; ?>)。

これを簡単に回避するには、トリプルイコール(完全比較)演算子を使用します。これは、型をチェックし、暗黙的に型キャストしません。

PS:a PHP fun fact:a == bb == aを意味するわけではありません。例を挙げて逆にすると:if ("e" == $item['price'])は実際には満たされません。 $ item ['price']は常に整数です。

8

==演算子は、値が異なるタイプであっても値を一致させようとします。例えば:

'0' == 0 will be true

型比較も必要な場合は、===演算子を使用します。

'0' === 0 will be false
8

PHPに== falseと "1"、 "on"、 "true"としての "0"、 "false"、 "off"の組み合わせを検証するためのかなり便利なメソッドがあります。 =しばしば見落とされがちですが、GET/POST引数の解析に特に役立ちます。

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );

このユースケースに完全に関連するわけではありませんが、類似性と事実を考慮すると、(文字列) "0"をfalseとして検証する質問をするときに検索結果が見つかる傾向があります。

http://www.php.net/manual/en/filter.filters.validate.php

6
Jim Morrison

通常の演算子は型を比較しないため、===の代わりに==を使用する必要があります。代わりに、アイテムの型キャストを試みます。

一方、===はアイテムのタイプを考慮に入れます。

  • ===は「等しい」を意味し、
  • ==は、「eeeeh ..ちょっと似ている」という意味です。
5
tereško

同じ奇妙な振る舞いにぶつかりながら、私がやった例で示すのが最善だと思います。私のテストケースを参照してください、そして、うまくいけば、それはあなたが行動をよりよく理解するのに役立つでしょう:

//Normal comparison using the == Operator
echo (0 == "0"); // true
echo (0 == "a"); // true
echo (0 == "safta!"); //true
echo (1000 == "bla"); //false. It appears that PHP has a weird behavior only with the number / string 0 / "0" according to the past 3 examples.
echo (23 == "23"); //true. So as we said, PHP has a problem (not a problem but weird behavior) only when the number / string 0 (or "0") is present
echo (23 == "24"); //false. values aren't equal (unlike last example). type is less relevant with the == operator as we can see.

//now using the === and !== Operators
echo ("0" === 0); //false, since === requires both value and type to be the same. here, type is different (int vs string)
echo ("0" !== 0); //true because they aren't the same in terms of === comparison (type is different and that's why its true)
echo ("bla" === "blaa"); //false because the values are not the same. The type is the same but === check for both equal type and equal value

//Now using casting and === Operator:
echo ((string)123 === "123"); //true. The casting of the int 123 to string changed it to "123" and now both vars have same value and are of same type
echo ((int)"123" === 123); //true. The casting of the string 123 to int, changed it to int, and now both vars are of same value and type (which is exactly what the === operator is looking for)

//Now using casting and == Operator. Basically, as we've seen above, the == care less for the
//type of var, but more to the value. So the casting is less relevant here, because even 
//without casting, like we saw earlier, we can still compare string to int with the == operator
//and if their value is same, we'll get true. Either way, we will show that:
echo ((string)123 == "123"); //true. The casting of the int 123 to string changed it to "123" and now both vars have same value and are of same type
echo ((int)"123" == 123); //true. The casting of the string 123 to int, changed it to int, and now both vars are of same value and type (which is exactly what the === operator is looking for)

それが役に立てば幸い。

1
Kosem