PHP 类型比较详解:松散比较与严格比较的区别

· PHP笔记 小技巧 PHP 入门笔记 · 0 阅读 · 约 4 分钟

PHP 类型比较详解:松散比较与严格比较的区别

写 PHP 的时候经常被 == 和 === 搞糊涂,尤其是这种类型转换比较“宽松”的版本。这篇笔记把常用的类型比较规则整理一下,方便查阅。

松散比较与严格比较

PHP 有两种比较方式:

  • ==:松散比较,只比较值,比较前会先做类型转换
  • ===:严格比较,值和类型都要相同才返回 true
var_dump(1 == "1");    // true
var_dump(1 === "1");   // false
var_dump(0 == "abc");  // true,字符串被转成 0(5.6 的坑)
var_dump(0 === "abc"); // false

常见松散比较结果示例

以下在 PHP 5.6 下运行的结果,注意 null 和空字符串的比较:

var_dump(null == "");     // true
var_dump(null == 0);      // true
var_dump(null == false);  // true
var_dump("" == false);    // true
var_dump("0" == false);   // true
var_dump("0" == 0);       // true
var_dump("abc" == 0);     // true(字符串开头不是数字就转成 0)

可以看到 null、""、0、false 在松散比较下几乎“一路相等”,所以在业务判断里建议尽量用 ===,避免出现莫名其妙的逻辑错误。

字符串与数字比较

PHP 5.6 中,字符串和数字比较时,会把字符串转成数字:

var_dump("123" == 123);      // true
var_dump("123abc" == 123);   // true,取字符串开头的数字部分
var_dump(" 123 " == 123);    // true,前后空格会被忽略
var_dump("1e2" == 100);      // true,支持科学计数法

如果字符串开头不是合法数字,会被转成 0,这也是 0 == "abc" 为 true 的原因。

数组的比较

数组松散比较时,两边元素数量相同、键和值都对应相等即可,顺序不影响 ==,但影响 ===:

$a = ['a' => 1, 'b' => 2];
$b = ['b' => 2, 'a' => 1];

var_dump($a == $b);  // true,键值对相同即可
var_dump($a === $b); // false,=== 要求顺序也一致

switch 语句的坑

switch 用的是松散比较,所以也会踩到类型转换的坑:

$value = 0;
switch ($value) {
    case "abc":
        echo "匹配了 abc";
        break;
    default:
        echo "没匹配";
}
// 输出:匹配了 abc

0 == "abc" 为 true,所以直接命中了第一个 case。写 switch 时最好先确认变量类型,或者改用 if 加 === 判断。

总结

  • == 会做类型转换,=== 不做,日常业务判断优先用 ===
  • null、0、""、false 在松散比较下容易互相“相等”
  • 字符串与数字比较时,非法数字字符串会被转成 0
  • switch 是松散比较,注意 case 的类型

养成习惯,能确定类型的地方一律用严格比较,可以省掉很多排查半天才发现的诡异 bug。