5

所以php网站上有这个页面,它显示了比较不同值的结果:

http://php.net/manual/en/types.comparisons.php

这是一个有用的参考,但我宁愿不必每次都访问此页面以确保我正在做正确的类型比较。所以我的问题是

PHP类型比较的逻辑背后是否有某种潜在的哲学/推理?

例如,我可以看到松散的比较:

  • 1、-1、“1”和“-1”可以视为TRUE,0和“0”可以视为FALSE;
  • 用 yield TRUE 比较数字的字符串值和数字本身;

但从那时起尝试建立模式就变得有点毛茸茸了。

4

7 回答 7

6

对于直接转换为布尔值,这就是它的工作原理。

  • 所有长度 > 0 的字符串都为真
  • 所有非 0 数字都为真
  • 所有非空数组都为真
  • 所有对象都是真实的

然后这些规则用于比较相同类型的变量:

  1. 如果对象的属性相等,则对象是等价的
  2. 如果它们的键和元素相等,则数组是等价的
  3. 如果字符串产生相同的输出,则它们是等效的
  4. 数字是等价的,如果它们在数学上是等价的
  5. 如果布尔值具有相同的值,则它们是等效的。

对于不同类型的变量,将上面列表中较高的类型转换为较低的类型,然后进行比较。

===!==运算符在比较之前不会强制转换,但您应该注意对象只有===当它们是相同的实例时才是。

真正奇怪的是数组,===如果它们具有以相同顺序定义的相同键和值。

$a = array("a"=>1, "b"=>2);
$b = array("b"=>2, "a"=>1);

$a == $b; // true
$a === $b; // false

并且empty()等价于!(bool)$var

例外情况

  • 将数组转换为字符串将触发通知并无济于事地转换为文本Array
  • 将没有 __toString方法的对象转换为字符串会导致致命错误。
  • 对象不会隐式转换为数组,因此任何时候将对象与数组进行比较都会产生错误(更新确认这是真的,即使对象实现了ArrayAccess接口)
于 2013-05-14T22:00:46.737 回答
4

对于严格===的比较,逻辑很简单:每个值实体只等于它自己,所以TRUE === TRUE, "1" === "1", but"1" !== 1等等。

当谈到==比较时,不幸的是没有经验法则,也没有明确的逻辑。这可能是因为各种形式的运算符是由不同的程序员实现的,没有中央设计决策。我能做的最好的就是为您提供此图表以打印并粘贴在显示器上:

PHP 相等图

该图的关键是:当且仅当和是上图中由一条线直接连接的两种类型时,A == B将是。例如,是因为和是直接相连的,而是因为没有线将两者连接起来。TRUEABarray() == NULLTRUEarray()NULLarray() == 0FALSE

用红色标记的线是棘手的(不明显的)等式

我省略了每个实体都将等于它自己(例如"1" == "1"等),但这应该很容易记住。

最后一点,我想解释一下为什么"php" == 0is TRUE(non empty, non number string is equal to 0):因为 PHP"php"在比较之前转换为 number ,并且由于它不是数字,所以它默认为0并进行 test TRUE

有趣的事实:这种关系没有分区!如果允许传递闭包,您可以轻松地说True 是 False 和 False 是 True,用四个简单的 PHP 语句破坏了数千年的哲学:D

于 2013-05-18T11:40:48.460 回答
2

如果该值包含某些内容,则可以说它是true。例如,11.123array("value")等都被视为true

如果可以说该值是空的或无效的(即缺少某些东西),那么它被视为false。例如,00.0array()等。

这种考虑变量的方式对于 PHP 来说并不特殊。许多其他语言以相同或相似的方式做到这一点。例如 Perl、C 和 Javascript,仅举几例。

于 2013-04-16T22:35:55.387 回答
2

imo 有一个非常简单的指南和规范中的错误,这可能会令人困惑。

严格比较检查数据类型和值的相等性。松散比较仅检查值是否相等。

对于一个对象(不是比较表的一部分),php 非常简单:如果该对象与另一个对象是相同的实例,那么它是严格相等的,否则它可能是松散相等的。

因此,一个 0 和一个“0”彼此松散地相等并且为假(以及任何字符串)。后者可以理解为所有字符串都不是数字,因此为假,等于假的数字为0,因此所有字符串都等于0。

null 和 array() 之间的比较更复杂。如果您检查使用 array() 创建的数组并进行松散严格的比较,那么它会返回 true。但是,如果您使用 is_null 检查它,那么它会返回 false。我认为后者更合乎逻辑,因为使用 array() 创建的 array() 不等于 '',其中 null 是。我认为函数 is_null() 和检查 == null 或 === null 之间的这种功能不一致是一个错误,因为使用两种不同的有效方法来检查一个值返回不同的结果是不应该的。根据函数 is_array(),Null 也不是数组,这是真的。根据函数 is_array(),空数组是一个数组,这也应该是真的。因此,null 等于 array() 永远不应该是真的。

于 2013-05-16T14:37:02.330 回答
1

没有特定的逻辑,但您可以找出一些模式。

  • “空”值(null, false, 0, 空字符串和字符串'0')评估为false
  • 数值的比较是隐式地将它们转换为整数,直到某个版本(当两个实际不同的长数字字符串被视为相等时存在错误,现在已修复)
  • 使用数组时,整数和数字索引之间没有区别,除非您使用显式strict参数调用 array_key_exists
  • 将数字与字符串进行比较隐式地将右参数转换为左参数的类型
  • return ($something);$something如果不是标量,则隐式转换为字符串
于 2013-05-15T20:31:09.820 回答
1

基本模式与 C 中使用的模式相同:为了进行布尔比较,任何非零都是真的。

从这个意义上说,空字符串或数组也是错误的。

要注意的毛茸茸的标量是'0',它(非常不方便)也被视为空,因为它被转换为整数。array(0)就在阵前一样棘手。

当使用严格的比较 ( ===and !==) 时,事情会更加理智。在实践中,将来自超全局变量和数据库的输入视情况进行转换通常是一个好主意,并从那时起使用这些运算符。

于 2013-05-16T21:13:16.400 回答
0

我是这样看的:

  1. PHP 被设计为一种 Web 编程语言,页面的所有输入都是基于字符串 [类似人类的感知] [顺便说一句,JavaScript 也是如此]
  2. 因此,所有看起来像数字的字符串(is_numeric() 函数),初步表现得像数字 [比较,强制转换]。
  3. 这就解释了为什么像“0”这样的极端情况首先被隐式地认为被强制转换为(int)0,然后才被强制转换为false
于 2013-05-17T14:24:44.607 回答