== 检查两个值在被 PHP 转换成同一种类型后是否相等。=== 检查它们是否相等,并且类型相同。所以 1 == "1" 是 true,而 1 === "1" 是 false。
大多数比较相关的 bug 都来自 == 做了你没料到的类型转换。比较好的默认做法是使用 === 和 !==,只有在确定需要类型转换时才改用 ==。
PHP 的所有比较运算符
| 运算符 | 名称 | 何时为真 |
|---|---|---|
$a == $b | 等于 | 类型转换后相等 |
$a === $b | 全等 | 相等且类型相同 |
$a != $b、$a <> $b | 不等于 | 类型转换后不相等 |
$a !== $b | 不全等 | 不相等,或类型不同 |
$a < $b、$a > $b | 小于,大于 | |
$a <= $b、$a >= $b | 小于等于,大于等于 | |
$a <=> $b | 太空船 | 返回 -1、0 或 1 |
松散比较和严格比较对照表
这张表的每个格子都由 PHP 8.3 计算得出。在 == 和 === 之间切换,点一下格子就能看到对应的表达式。== 的表格在 null、""、"0" 和 [] 这几行里充满了意外;=== 的表格则只有对角线为真。
| $a == $b | true | false | 1 | 0 | -1 | "1" | "0" | "" | null | [] | "php" | "10" | "1e1" |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true | |||||||||||||
| false | |||||||||||||
| 1 | |||||||||||||
| 0 | |||||||||||||
| -1 | |||||||||||||
| "1" | |||||||||||||
| "0" | |||||||||||||
| "" | |||||||||||||
| null | |||||||||||||
| [] | |||||||||||||
| "php" | |||||||||||||
| "10" | |||||||||||||
| "1e1" |
== 如何比较不同类型的值
下面是 PHP 8 遵循的规则,按实际中的重要程度排列:
- 两个数字字符串按数字比较:
"10" == "1e1"和"1" == "01"都是true。 - 数字和数字字符串:字符串会转换成数字。
100 == "1e2"是true。 - 数字和非数字字符串:从 PHP 8 开始,数字会转换成字符串,然后按字符串比较。
0 == "a"是false(在 PHP 7 中是true)。 - 任意值和布尔值:两边都转换成布尔值。
"a" == true和[] == false都是true。 - null 和字符串:
null会变成"",所以null == ""是true,但null == "0"是false。和其他任何类型比较时,null都按false来比较。 - 两个数组:拥有相同的键值对时相等。
最后一行说明了为什么用 null 做大小比较通常没有意义:null 变成 false,-1 变成 true,而 false < true。
不等于:!= 与 !==
!= 和 <> 是同一个运算符,!== 是它的严格版本。对于 strpos 这类会返回 0 或 false 的函数,两者的区别最重要:
0 != false 是 false,因为 0 会转换成 false。0 !== false 是 true,因为整数不是布尔值。array_search 以及不带严格标志的 in_array 也有同样的陷阱。
比较字符串
< 和 > 按字节比较字符串(对于普通 ASCII 字符就是按字母顺序)。如果两个字符串都是数字字符串,就按数字比较。要忽略大小写或按“自然”顺序比较,请使用这些函数:
太空船运算符 <=>
$a <=> $b 在 $a 较小时返回 -1,相等时返回 0,$a 较大时返回 1。它使用和 <、== 相同的规则,是编写排序回调最简短的方式。
用 <=> 比较两个数组时会逐个元素比较,回调正是靠这一点先按年龄、再按名字排序的。更多排序方法见数组排序页面。
常见错误:用 == 比较浮点数
浮点数以二进制存储,所以很多十进制数只是近似值。0.1 + 0.2 并不完全等于 0.3,而 == 能看出这个差别。
处理金额时,请把以分为单位的整数存起来,再用 === 比较。
常见问题
PHP 中 == 和 === 有什么区别?
== 先把两边转换成同一种类型再比较,所以 1 == "1" 是 true。=== 只有在值相等且类型相同时才为真,所以 1 === "1" 是 false。除非你需要类型转换,否则请使用 ===。
PHP 中 0 == "a" 是 true 吗?
从 PHP 8 开始不是了。当数字和非数字字符串比较时,PHP 8 会把它们当作字符串比较,所以 0 == "a" 是 false。在 PHP 7 中,字符串会被转换成 0,结果是 true。
PHP 中 != 和 !== 有什么区别?
!=(以及它的别名 <>)是 == 的反面:值在类型转换后相等时它为假。!== 是 === 的反面:值不同或类型不同时它为真,所以 0 !== false 是 true,而 0 != false 是 false。
PHP 中怎么比较两个浮点数?
不要对浮点运算的结果使用 ==:0.1 + 0.2 == 0.3 是 false。应该用一个很小的容差来比较它们的差值:abs($a - $b) < PHP_FLOAT_EPSILON,或者把两者都四舍五入到你关心的精度。