为什么PHP认为0等于字符串?

时间:2011-07-27 10:45:26

标签: php string numbers evaluate

我有以下代码:

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

打算将商品价格初始化为0,然后获取相关信息。如果价格被告知为'e',则表示交易而非卖出,卖出作为负数存储在数据库中。

还有可能将价格保留为0,因为该项目是奖金,或者因为价格将在稍后设定。

但是,每当未设置价格时,其初始值为0,上面指出的if循环评估为真,价格设置为-1。也就是说,它认为0等于'e'。

如何解释?

编辑: 当价格提供为0(初始化后)时,行为不稳定:有时if评估为true,有时评估为false。

9 个答案:

答案 0 :(得分:95)

你正在做==,为你挑选出类型。

0是一个int,因此在这种情况下,它会将'e'强制转换为int。哪个不可解析为一个,并将成为0。字符串'0e'将变为0,并且匹配!

使用===

答案 1 :(得分:45)

这是由于PHP如何执行== comparison operator表示的比较操作:

  

如果您将数字与字符串进行比较或比较涉及数字字符串,则每个字符串都会转换为数字,并且数字会进行比较。 [...]当比较为===!==时,类型转换不会发生,因为这涉及比较类型和值。

由于第一个操作数是数字(0),第二个是字符串('e'),因此字符串也会转换为数字(另请参阅table Comparison with Various Types)。字符串数据类型的手册页定义了string to number conversion的完成方式:

  

在数值上下文中计算字符串时,结果值和类型确定如下。

     

如果字符串不包含任何字符“.”,“e”或“E”,则数值适合整数类型限制(由PHP_INT_MAX),字符串将被计算为整数。在所有其他情况下,它将被评估为浮动。

在这种情况下,字符串为'e',因此它将被评估为float:

  

该值由字符串的初始部分给出。如果字符串以有效数字数据开头,则这将是使用的值。否则,该值将为0(零)。有效数字数据是可选符号,后跟一个或多个数字(可选地包含小数点),后跟可选指数。指数是“e”或“E”后跟一个或多个数字。

由于'e'不以有效的数字数据开头,因此评估为浮动0

答案 2 :(得分:13)

"ABC" == 0

评估true,因为第一个 "ABC"转换为整数并变为0 然后将其与{{1}进行比较}。

这是PHP语言的奇数行为:通常会将0提升为字符串0,然后将其与"0"进行比较结果"ABC"。 也许这就是其他语言中发生的情况,例如JavaScript,弱比较false评估"ABC" == 0

进行严格的比较可以解决问题:

false

评估"ABC" === 0

但是如果我需要将数字作为字符串与数字进行比较呢?

false

评估"123" === 123 ,因为左右术语的类型不同。

实际需要的是一个弱的比较,没有PHP类型杂耍的陷阱。

解决方案是明确地将术语提升为字符串,然后进行比较(严格或弱无关紧要)。

false

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

,而

true

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

应用于原始代码:

false

答案 3 :(得分:8)

==运算符将尝试匹配值,即使它们属于不同类型。例如:

'0' == 0 will be true

如果您还需要类型比较,请使用===运算符:

'0' === 0 will be false

答案 4 :(得分:8)

你的问题是双等号运算符,它会将正确的成员类型化为左边的类型。如果您愿意,请使用严格。

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

让我们回到你的代码(上面复制)。在这种情况下,在大多数情况下,$ item ['price']是一个整数(显然,除非它等于e)。因此,根据PHP的法律,PHP会将"e"类型转换为整数,从而产生int(0)。 (不相信我?<?php $i="e"; echo (int)$i; ?>)。

为了轻松摆脱这种情况,请使用三重相等(精确比较)运算符,它将检查类型并且不会隐式进行类型转换。

P.S:PHP有趣的事实:a == b并不意味着b == a。举个例子并反过来:{$ 1}}实际上永远不会实现,前提是$ item ['price']总是一个整数。

答案 5 :(得分:6)

在PHP中有一个相当方便的方法,用于验证混合“0”,“假”,“关闭”为== false和“1”,“on”,“true”为== true,这经常被忽略。它对于解析GET / POST参数特别有用:

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

这与用例并不相关,但考虑到相似性和事实,这是搜索结果,当询问验证(字符串)“0”为错误时,我认为它会帮助其他人。

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

答案 6 :(得分:5)

您应该使用===而不是==,因为普通运算符不会比较类型。相反,它会尝试对项目进行类型转换。

同时===考虑了项目的类型。

  • ===表示“等于”,
  • ==表示“eeeeh ..有点像”

答案 7 :(得分:2)

基本上,请始终使用===运算符来确保类型安全。

Enter image description here

Enter image description here

答案 8 :(得分:1)

我认为最好以我做过的例子来展示,同时遇到同样奇怪的行为。查看我的测试用例,希望它可以帮助您更好地理解行为:

//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)

希望有帮助。