Menu

PHP 空合并运算符:?? 和 ??=

PHP 空合并运算符返回它左侧的值,除非左侧为 null 或未设置:$name = $_GET['name'] ?? 'Guest';。遇到不存在的变量或数组键,它从不发出警告。学习 ?? 链式写法、??= 赋值、?? 与 ?: 的区别,以及空安全运算符 ?->。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

如果左侧的值存在且不为 null,?? 就返回它,否则返回右侧的值:$name = $_GET['name'] ?? 'Guest';。和直接读取键不同,当变量或数组键不存在时,它从不发出警告。

第一次运行时没有查询字符串,所以两个默认值都会被使用。在“页面”标签页中点击一个链接,脚本会再次运行,这时 $_GET 已经有了数据。如果第一次运行时不用 ?? 直接读取 $_GET["name"],在常规的 PHP 环境中会打印 Warning: Undefined array key "name"。关于请求数据的更多内容,请参阅 GET和_GET 和 _POST 页面。

?? 是 isset() 检查的简写

$a ?? $b 的含义与 isset($a) ? $a : $b 完全相同。它适用于变量、任意深度的数组键和对象属性,并且会在遇到第一个缺失的部分时安静地停下。

这里的检查和 isset 所做的完全一样,所以一个存在但值为 null 的键也会取默认值。

用 ?? 链式尝试多个来源

?? 是右结合的,你可以想串多少个就串多少个。PHP 会返回第一个已设置且不为 null 的操作数。

??= 只在为 null 时赋值

只有当 $a 未设置或为 null 时,$a ??= $b 才会把 $b 存进 $a。这是填充默认值,或者只计算一次然后重复使用某个结果的最简写法。

??= 右侧的表达式只在真正赋值时才会求值,所以 computing 4 只出现了一次。

?? 与 ?:(简写三元运算符)

?? 检查的是 null,?: 检查的是真假值。遇到 0、"" 和 "0" 这样的值时,它们会给出不同的结果:

数量为 "0" 是真实的输入:?? 会保留它,?: 则会把它替换掉。单独使用 ?: 会因为键不存在而发出警告,所以代码中把它写成了 ($inputs[$key] ?? null) ?: ...。三元运算符页面 介绍了 ?: 本身。

空安全运算符 ?->

?-> 是同一思路的对象版本,在 PHP 8 中加入。如果左侧的对象是 null,整条链就会停下并返回 null,而不是抛出像 Call to a member function getAddress() on null 这样的 Error。在末尾加上 ?? 即可提供默认值。

用户 2 存在但没有地址,用户 3 则根本不存在。两者都会落到 ?? "unknown" 默认值上,而不会出错。

常见错误:?? 的优先级很低

?? 的结合力比 . 和算术运算符都要弱。所以在 "Count: " . $count ?? 0 中,PHP 会先构建字符串 "Count: " . $count,它永远不会是 null,默认值也就永远用不上。

只要 ?? 表达式位于一个更大的表达式中,就用括号把它括起来。

常见问题

PHP 中 ?? 是什么意思?

?? 是空合并运算符。如果 $a 存在且不为 null,$a ?? $b 返回 $a,否则返回 $b。它是 isset($a) ? $a : $b 的简写,当 $a 或某个数组键未定义时也不会发出警告。

PHP 中 ?? 和 ?: 有什么区别?

只有当左侧为 null 或未设置时,?? 才会取后备值,所以 0 ?? 5 是 0,'' ?? 'x' 是 ''。只要左侧是假值,?: 就会取后备值,所以 0 ?: 5 是 5。另外,?: 遇到未定义的变量和键会发出警告,?? 不会。

PHP 中 ??= 有什么作用?

只有当 $a 为 null 或未设置时,$a ??= $b 才会把 $b 赋给 $a;否则 $a 保持不变。它是 $a = $a ?? $b; 的简写,在 PHP 7.4 中加入。

PHP 中的空安全运算符 ?-> 是什么?

只有当 $obj 不为 null 时,$obj?->method() 才会调用该方法;如果它是 null,整条链会返回 null,而不是抛出错误。和 ?? 组合使用可以提供默认值:$user?->getAddress()?->city ?? 'unknown'。它在 PHP 8.0 中加入。

Coddy 编程语言插图

和 Coddy 一起学编程

开始