PHP字符串比较出现意外类型转换

4

在比较一些字符串值时,我在PHP中遇到了一个奇怪而意外的行为。下面的前两个语句返回了true,但我希望它们返回false。最后一条语句按预期返回false。我知道PHP的类型转换,但根据文档,我理解的是类型转换发生在比较两种不同的数据类型(如字符串和整数)时。然而,在下面的示例中,两个文字都是字符串。这是否意味着当您在PHP中进行字符串比较时,它会检查两个字符串是否看起来像整数,如果是,则将它们都强制转换为整数,然后比较这些整数值。所以我的问题是,在什么条件下会发生这种行为,PHP中的字符串比较如何工作?

var_dump("10" == "10.0000");
var_dump("10" == "+10.");
var_dump("10" == "10 ");

#output
bool(true)
bool(true)
bool(false)

更新

那么下面baba的回答涉及数字字符串的比较 真的帮助我理解了正在发生的事情。函数 is_numeric 将返回一个字符串是否被认为是数字字符串。有趣的是,"10 " 不被认为是数字字符串,但 " 10" 是。我查看了PHP源代码,我相信 is_numeric的实现 在 is_numeric_string_ex 函数中。从这可以确定PHP何时将把一个字符串视为数字字符串。


1
你可以使用 === 或者更明确的 strcmp/strcasecmp,而不是接受类型转换。 - DCoder
我知道那些选项。我不在寻找替代品,我希望理解“==”运算符的作用及其类型转换应用的确切时间和原因。 - Marwan Alsabbagh
2
不要使用==运算符。像许多PHP功能一样,它包含太多的魔法。你可以尝试理解所有类型转换的异常,但最好避免使用它。 - GolezTrol
3个回答

2
由于空格的位置,您会收到错误提示。正确的写法应该是在空格前后都添加引号,这样才能返回真值。
var_dump("10" == " 10"); // true

如果你运行

var_dump("10" == "10 "); //false

你实际运行的是字符串,因为它会被视为字符串处理。

var_dump("10" == 0); //false

这是因为类型转换会将"10 "转换为0,这在PHP文档中有说明。 PHP文档中提到:如果您将数字与字符串进行比较或比较涉及数字字符串,则每个字符串都会转换为数字,并以数字方式执行比较。这些规则也适用于switch语句。当使用===或!==进行比较时,不会进行类型转换,因为这涉及比较类型和值。
如果您想欺骗类型转换,可以…
var_dump("10" == 0 + "10 ");  // true

这是因为

PHP自动类型转换的一个例子是加法运算符“+”。如果任一操作数是浮点数,则两个操作数都将被视为浮点数进行计算,结果将是浮点数。否则,操作数将被解释为整数,并且结果也将是整数。请注意,这不会改变操作数本身的类型;唯一的变化在于如何评估操作数以及表达式本身的类型。


你能否提供 PHP 文档中包含该语句的链接?谢谢。 - Marwan Alsabbagh
我认为"10 "不会像你上面所写的那样变成0,如果你执行(int)("10 "),它会给你int(10)。 - Marwan Alsabbagh
(int)("10 ")+"10 " 是一样的吗?如果你在一个字符串前面加上 ==,那么你做的就是同样的事情,它总是返回0。 - Baba

1

我想确定的答案可能埋藏在 php-src/Zend/zend_operators.c 中的 compare_function 和其中使用的宏定义中。


0
在这种情况下,除了最后一个字符串外,所有的“字符串”都被视为浮点数或整数,然后进行比较。这就是为什么第1行和第2行会返回true。
在第3行中,字符串中有一个空格,这意味着对于php来说它是一个“真正”的字符串,并且该行会比较字符串。
我也不喜欢“松散类型”的语言,但对于php来说,这就是它工作的方式。

1
我理解了。我在帖子中描述了同样的过程,但我想知道这种行为是否有记录在任何地方。或者有人可以发布实际进行这些决策的 PHP 内部代码片段。 - Marwan Alsabbagh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接