【问题标题】:Several PHP type-juggling comparisons, such as empty string and an empty array, return unexpected results几个 PHP 类型杂耍比较,例如空字符串和空数组,返回意外结果
【发布时间】:2016-02-09 10:52:57
【问题描述】:

三等号我想每个人都明白;我的怀疑是关于双重平等。请阅读下面的代码。

<?php
//function to improve readability
function compare($a,$b,$rep)
{
    if($a == $b)
        echo "$rep is true<br>";
    else
        echo "$rep is false<br>";
}

echo "this makes sense to me<br>";
compare(NULL,0,'NULL==0');
compare(NULL,"",'NULL==""');
compare(NULL,[],'NULL==[]');
compare(0,"",'0==""');

echo "now this is what I don't understand<br>";
compare("",[],'""==[]');
compare(0,[],'0==[]');
compare(0,"foo",'0=="foo"');

echo "if I cast to boolean then it makes sense again<br>";
compare("",(bool)[],'""==(bool)[]');
compare(0,(bool)[],'0==(bool)[]');
?>

输出:

这对我来说很有意义

NULL==0 is true
NULL=="" is true
NULL==[] is true
0=="" is true

这就是我不明白的地方

""==[] is false
0==[] is false
0=="foo" is true

如果我转换为布尔值,那么它再次有意义

""==(bool)[] is true
0==(bool)[] is true

我希望一个空数组与一个空字符串或整数 0“相等”。我不希望整数 0 与字符串“foo”“相等”。老实说,我并不真正了解 PHP 在幕后做什么。有人可以向我解释一下这里发生了什么吗?

【问题讨论】:

  • 不要试图理解 PHP,只管学习/参考任意规则表:php.net/manual/en/types.comparisons.php
  • @John,我认为您建议的副本不正确。这里的问题是问为什么""==[] 被评估为false,尽管PHP 的类型规则很松散(我希望转换也能返回true)。我不记得以前在这里看到过这个问题。你会考虑重新开放吗?
  • @Halfer 是的。我已经这样做了。
  • @halfer。凉爽的。投票支持我的答案?

标签: php boolean


【解决方案1】:

正如有人已经说过的,PHP 自动转换规则可能非常棘手,除非您知道双方将属于同一类型,否则值得使用 ===。不过我相信我可以解释这一点:

""==[] (returns false)

初始字符串"" 表示比较将是一个字符串,因此[] 被强制转换为一个字符串。发生这种情况时,比较的右侧将设置为单词Array。因此,您正在进行此比较:

"" == "Array" (returns false)

因此false 是正确的结果。

编辑:下面的有用评论使我对我的回答 via this live code example 产生怀疑。我应该有兴趣看看提供了哪些其他答案。

【讨论】:

  • 是的,我也试过了。事实上,这正是我的问题。如果我无法理解 == 的工作原理,我无法 100% 放心地使用它。当然,我总是可以使用 === 但有时 == 真的很方便。如果我可以在不看表格的情况下预测结果...
  • 这是一个很好的测试@Oliver,我没有现成的答案。 0==[] 也让我难过。我想知道这里是否有一些半类型检查,对于一侧是数组的情况。
  • @2Noob2Good:是的,根据我的回答,请使用===(或进行显式转换),除非您知道双方将始终属于同一类型。
  • 实际情况是,在后台会有一些硬编码规则。 PHP 作者添加它们的想法是它们会使事情变得更简单,但实际上使语义更复杂...
  • 有一个方便的图表here。我预计这些规则不会很快改变。松散的打字可能是一种祝福……也是一种诅咒。
【解决方案2】:

简单的答案是,这就是 php 设计的工作方式。

文档comparison operatorscomparison tables 中明确定义了结果。

数组(您的前两个查询)和字符串之间的 == 比较始终导致错误。

在数字和字符串之间的 == 比较(您的第三个查询)中,字符串被转换为数字,然后进行数字比较。在 0=='foo' 的情况下,字符串 'foo' 在数值上计算为 0,测试变为 0==0 并返回 true。如果字符串是“数字”,例如"3" 那么你的情况的结果是假的(0 不等于 3)。

设计是否“正确”(无论这意味着什么)是有争议的。这当然并不总是立即显而易见的。可以在Bug#54547 中找到辩论的潜在愤怒的一个说明性示例,其中开发人员强烈认为该设计植根于 php 作为一种 Web 语言的历史,其中所有内容都是字符串并且应该单独放置,而其他人则认为 php"违反了最小意外原则”。

为避免不确定性,请尽可能使用 ===,这样做的好处是可能会在您的代码中显示可能无效的假设。

【讨论】:

  • 阅读了那个错误报告,在我看来,改变是有可能的,但是有一群激进的人愿意滥用核心开发者,所以决定关闭。如果不出意外,它演示了如何不支持错误报告 ;-)
猜你喜欢
  • 2012-10-04
  • 2013-09-07
  • 2012-02-22
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2013-03-26
  • 2012-10-18
  • 1970-01-01
相关资源
最近更新 更多