为什么在传递看似数字的字符串时 is_numeric() return 为 false?

Why does is_numeric() return false when passed a seemingly numeric string?

我正在尝试理解 PHP 中的数字字符串。 我有以下代码:

var_dump(5 * "10 abc");
var_dump(is_numeric("10 abc"));

这给了我输出:

int(50)
bool(false)

这让我感到困惑,因为字符串 "10 abc" 似乎在第一个表达式中被解释为数字字符串(因此 int(50) 输出并且没有关于使用的警告一个非数值),但是当 运行 通过 is_numeric() 函数时它 returns 为假,表明它实际上不是一个数字字符串。

我花了一些时间查看文档以了解此行为,但找不到任何具体答案,有人可以帮助解释导致此行为的原因吗?

我知道 PHP 8.0.0 对被认为是数字字符串的内容进行了一些更改,但这是 PHP 7.1.33 我现在正在尝试了解。

我认为理解您描述的行为的最简单方法是仅仅因为字符串 不是数字 ,这并不意味着它不能 被强制转换或视为数字.

你的第一行代码

var_dump(5 * "10 abc");

将字符串视为数字,一旦遇到无效字符,它就会忽略之后的所有内容。

你的另一行代码

var_dump(is_numeric("10 abc"));

实际上表现得更聪明,会像人一样问自己,我们这里处理的是一个数字串吗?答案是否定的(因为那些相同的无效字符)。

PHP 8.0 在这里接受了“Saner 数字字符串”RFC 的 RFC 作者。

"10 abc"不是一个数字串,而是一个前导-数字串,意思是字符串的开头看起来像一个数字,但它不是一个,因为字符串中的某个点存在乱码(这包括空格)。

因为 is_numeric() 根据 PHP 的定义检查一个值是否被视为数字(在 PHP 8.0 之前意味着前导空格后跟 + 或 - 符号和任何整数、普通十进制数或指数表示法的数字),它将 return false 用于仅被视为前导数字的字符串。

然而,算术运算尝试将它们的操作数转换为适当的数字类型(int 或 float),因此 "10 abc" 被转换为 10 因为 PHP 将转换前导- 数字字符串到它的前导数值。

可以在 technical background section of the PHP RFC.

中找到更多“有趣”的细节和边缘案例