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

为什么PHP认为0等于一个字符串?,php,string,numbers,evaluate,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),上面指

我有以下代码:

$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。*

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

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

==意味着等于, ==表示eeeeh。。有点像
==运算符将尝试匹配值,即使它们是不同类型的值。例如:

'0' == 0 will be true
如果还需要类型比较,请使用===运算符:

'0' === 0 will be false
您正在执行==这将为您整理类型

0是一个整数,因此在本例中,它将把“e”转换为一个整数。该整数不可分解为1,将变为0。字符串“0e”将变为0并匹配

使用===

发件人:

使用==和其他非严格表达式比较字符串和数字 比较运算符当前的工作方式是将字符串强制转换为数字, 然后对整数或浮点数执行比较。这 结果在许多令人惊讶的比较结果中,最显著的是 即0==foobar返回true

但是,此行为在以下方面发生了更改:

当与数字字符串进行比较时,PHP8使用数字比较。 否则,它会将数字转换为字符串并使用字符串 比较

PHP7

PHP8在进行比较之前将数字转换为字符串

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

这是一个重大变化,因此它是在一个新的主要PHP版本中实现的。此更改破坏了依赖于旧行为的脚本中的向后兼容性。

这是由于PHP如何执行比较操作,表示:

如果将数字与字符串进行比较,或者比较涉及数字字符串,则会将每个字符串转换为数字,并以数字形式执行比较。[…]当比较为===或!==时,不会发生类型转换因为这涉及到比较类型和值

由于第一个操作数是数字0,第二个操作数是字符串“e”,因此该字符串也会转换为数字,请参见。字符串数据类型的手动页面定义了如何执行:

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

如果字符串不包含任何字符“.”、“e”或“e”,并且数值符合PHP_INT_MAX定义的整数类型限制,则字符串将作为整数计算。在所有其他情况下,它将作为浮动进行评估

在这种情况下,字符串为“e”,因此将作为浮点值进行计算:

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


由于“e”不是以有效的数字数据开头的,它的计算结果是浮点0。

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

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );
这与这个用例并没有完全的关系,但考虑到相似性和事实,当问到验证string0为false的问题时,这是搜索结果,我认为这会帮助其他人


您的问题是双相等运算符,它将右成员的类型转换为左成员的类型。如果您愿意,请使用strict

if($item['price'] == 'e') {
    $item['price'] = -1;
}
让我们回到上面复制的代码。在这种情况下,在大多数情况下,$item['price']是一个整数,除非它显然等于e。同样地,根据PHP的规律,PHP将e类型转换为整数,从而生成int0。不相信我

要轻松摆脱这种情况,请使用triple equal exact comparison操作符,它将检查类型,而不会隐式地进行类型转换

注意:一个有趣的事实:a==b并不意味着b==a。举个例子,反过来说:如果e==$item['price']始终是整数,那么实际上永远不会满足$item['price']

"ABC" == 0
计算为true,因为第一个ABC已转换 设置为整数并变为0,然后将其与0进行比较

这是PHP语言的一种奇怪行为:通常情况下,人们希望0被提升为字符串0,然后与ABC进行比较,结果为false。 在其他语言(如JavaScript)中,弱比较ABC==0的计算结果为false,可能就是这种情况

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

"ABC" === 0
计算结果为假

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

计算结果为false,因为左项和右项的类型不同

实际上需要的是一个弱比较,而不存在PHP类型转换的陷阱

解决方案是显式地将术语提升为字符串,然后进行比较严格或弱不再重要

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

真的

假的

适用于原始代码:

$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -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). 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)
基本上,始终使用===运算符来保证类型安全


我发现使用triple===而不是double==可以提供预期的行为。但这仍然很奇怪。参考资料在PHP手册的第章中有充分的解释,并在中进行了说明。如果唯一可能的字符串类型是“e”,您就不能进行is_string$item[price]检查吗?这将比==更有效一点。[需要引用]在字符串和整数之间的弱比较中,字符串将转换为整数,而不是整数升级为字符串。ifstring$item['price']='e'修复了这种奇怪的行为。有关更多详细信息,请注意@Paolo在下面的注释中的另一种情况,其中使用双等于运算符时,0整数等于任何其他字符串。我明白了。现在可以使用typecast:ifstring$item['price']='e'{$item['price']=-1;}但不应该这样做。只需使用===运算符或疯狂比较的另一个缺点。棘手的一个。刚碰到这个,很惊讶为什么string==0。我必须记住。当我在循环字符串键时,我也在抓这个问题,但是数组有一个初始的“零”索引项,它在第一个字符串键比较时一直导致true。我像什么?如何在。。。果然,这个答案澄清了这一点!我很惊讶整个问题没有一个被接受的答案。php设计了几乎所有的东西,使之易于比较,然后加入了一些陷阱,只会毁掉我们的一天。这与PHP的其他设计理念不符。除非有欺骗,否则哲学是存在的???特别是因为e是对的,e是错的,这是一个伟大的考验,我也这么做了,但我用它做了一张漂亮的桌子。看到我的答案了吗
(string)"123" === (string)0
$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -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). 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)