127

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

$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と評価される場合もあります。*

4

9 に答える 9

135

あなたはあなた==のためにタイプを分類することをしています。

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

使用する===

PHP.netから:

==およびその他の非厳密な比較演算子を使用した文字列と数値の比較は、現在、文字列を数値にキャストし、続いて整数または浮動小数点数で比較を実行することによって機能します。これにより、多くの驚くべき比較結果が得られます。その中で最も注目すべきは、0=="foobar"がtrueを返すことです。

ただし、この動作はPHP8.0で変更されまし

数値文字列と比較する場合、PHP8は数値比較を使用します。それ以外の場合は、数値を文字列に変換し、文字列比較を使用します。

PHP 7

0 == 'foobar' // true
0 == '' // true
4 == '4e' // true (4e is cast as a number and becomes 4)

PHP 8は、比較を行う前に数値を文字列に変換します

0 == 'foobar' // false
0 == '' // false
4 == '4e' // false ('4e' is considered non-numeric therefore 4 is cast as a string and becomes '4')

これは大きな変更であるため、新しいメジャーPHPバージョンで実装されました。この変更により、古い動作に依存するスクリプトの下位互換性が失われます。

于 2011-07-27T10:49:01.317 に答える
48

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

数値を文字列と比較する場合、または比較に数値文字列が含まれる場合、各文字列は数値に変換され、比較は数値で実行されます。===[…]型変換は、比較が行われている場合、またはこれには型と値の比較が含まれるため、行われません!==

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

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

.文字列に文字' '、' e'、または''のいずれも含まれておらずE、数値が整数型の制限(で定義されているPHP_INT_MAX)に適合する場合、文字列は整数として評価されます。他のすべての場合、フロートとして評価されます。

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

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

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

于 2011-12-29T19:22:53.863 に答える
24
"ABC" == 0

最初に整数に変換されてからになるためtrue、評価されます。 "ABC"0 0

これはPHP言語の奇妙0な動作です。通常、文字列にプロモートされてから結果"0"と比較されることが期待されます。おそらくそれは、弱い比較が評価するJavaScriptのような他の言語で起こることです。"ABC"false"ABC" == 0false

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

"ABC" === 0

評価しfalseます。

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

"123" === 123

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

実際に必要なのは、PHP型ジャグリングの落とし穴のない弱い比較です。

解決策は、用語を文字列に明示的にプロモートしてから比較を行うことです(厳密か弱いかはもう問題ではありません)。

(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;
}
于 2018-02-21T17:59:18.060 に答える
8

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

'0' == 0 will be true

タイプ比較も必要な場合は、===演算子を使用してください。

'0' === 0 will be false
于 2011-07-27T10:47:46.067 に答える
8

問題は、右のメンバーを左のタイプに型キャストするdoubleequal演算子です。必要に応じてstrictを使用してください。

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

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

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

PS:PHPのおもしろい事実:a == bそれを意味するものではありませんb == a。例を見て逆にするとif ("e" == $item['price'])、$ item ['price']が常に整数である場合、実際には実行されません。

于 2013-03-29T14:47:20.983 に答える
6

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

一方、===アイテムの種類を考慮に入れています。

  • ===「等しい」を意味し、
  • ==「ええと..ちょっと似ている」という意味です
于 2011-07-27T10:47:39.840 に答える
6

PHPには、「0」、「false」、「off」の組み合わせを== falseとして検証し、「1」、「on」、「true」を==trueとして検証するためのかなり便利な方法があります。これは、GET/POST引数の解析に特に役立ちます。

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

このユースケースとはあまり関係がありませんが、類似性と事実を考えると、これは、(文字列)「0」をfalseとして検証する質問をしたときに検索で見つかる傾向がある結果です。他の人に役立つと思いました。

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

于 2012-04-26T05:54:06.233 に答える
4

===基本的に、型の安全性を保証するために、常にオペレーターを使用してください。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

于 2020-03-25T10:04:59.597 に答える
2

同じ奇妙な振る舞いに遭遇しながら、私が行った例で示すのが最善だと思います。私のテストケースを参照してください。うまくいけば、動作をよりよく理解するのに役立ちます。

// 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). The 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 it's true)
echo ("bla" === "blaa"); // false because the values are not the same. The type is the same, but === checks 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 variables 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 variables 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)
于 2019-02-15T11:31:52.693 に答える