PHP 8 已经发布。它对相等运算符的行为进行了更改。根据文档,这就是它现在的行为方式:
数字和非数字字符串之间的非严格比较现在通过将数字转换为字符串并比较字符串来工作。
然而,这个表达式在 PHP 8 和早期版本的 PHP 中都为真:
42 == " 42" // true
这对我来说没有意义。根据文档,数字应该转换为字符串"42"
,这肯定不等于字符串" 42"
,对吧?
在 PHP 8 和 PHP 7 中42 == " 42"
是这样,在 PHP 7 和 PHP 8 中"42" == " 42"
都是这样。
我认为您对等式运算符==
在 PHP 中的工作方式有误解。在 PHP 8 和早期版本的 PHP 中,相等运算符处理看起来是数字的字符串与其他字符串不同:
<?php
// the == operator does type juggling and also handles numerical strings differently:
var_export("42" == "42"); // true
var_export(42 == "42"); // true
var_export("42" == " 42"); // true
var_export("42" == "42 "); // false in PHP 7 and true in PHP 8
var_export("42" == "042"); // true
var_export("10" == "1e1"); // true
var_export("abc" == " abc"); // false
var_export("42" == "abc 42"); // false
echo "\n";
// the === operator does not do type juggling and does not handle numerical strings differently:
var_export("42" === "42"); // true
var_export(42 === "42"); // false
var_export("42" === " 42"); // false
var_export("42" === "42 "); // false
var_export("42" === "042"); // false
var_export("10" === "1e1"); // false
var_export("abc" === " abc"); // false
var_export("42" === "abc 42"); // false
echo "\n";
即使在 PHP 8 中,==
操作符也确实类型杂耍,并且它以不同的方式处理数字字符串。这个原则没有改变。PHP 8 中的变化是:
==
在 PHP 8 中与 PHP 7 中用于数字和非数字字符串之间的比较的行为不同关于后一点,请阅读:
[在 PHP 8 中] 对数字字符串处理进行了更改,使其更加直观且不易出错。现在允许在数字字符串中使用尾随空格,以便与前导空格的处理方式保持一致。这主要影响:
is_numeric()
功能_- 字符串到字符串的比较
- 类型声明
- 递增和递减操作
您引用的文档实际上是正确的,但可能会更清楚:
数字和非数字字符串之间的非严格比较现在通过将数字转换为字符串并比较字符串来工作。
我将关键短语“非数字字符串”加粗。
在 PHP 的各个部分中,“数字字符串”的概念是一种伪类型:任何看起来像数字的字符串都可以被视为语言的一部分。这是为了帮助 PHP 的主要用例从 Web 请求中获取数据(始终是字符串)并在操作中使用它(可能希望将其视为数字)。
这发挥作用的地方之一是==
操作员,它试图“聪明”地了解您要比较的内容。
如果 PHP 决定==
运算符的两边都是数字或数字字符串,它将通过将它们都转换为整数(或浮点数,如果合适的话)并查看它们是否具有相同的数值来执行比较。“数字字符串”的定义非常广泛,并且允许使用前导空格;从 PHP 8 开始,它现在还允许尾随空格,以保持一致性。
所以在你的例子中," 42"
是一个“数字字符串”,42
是一个实际数字,所以执行的比较是(int)" 42" === 42
您的报价中描述的更改是针对一侧是实际数字(整数或浮点数)而另一侧是非数字字符串的情况,这是 PHP 决定“看起来不像数字”的情况. 在旧版本的 PHP 中,这也将转换为 int,因此"hello" == 0
评估(int)"hello" === 0
,即true
. 在 PHP 8 中,这种情况转换为字符串,因此"hello" == 0
评估"hello" === (string)0
,即false
.