?? 运算符仅对 null 和未定义值提供默认值,不将 0、''、false 视为空;用于安全取数组或超全局变量值,支持链式兜底;??= 是其赋值简写,具短路特性;混用 ?? 与 ?: 需注意优先级;它不适用于未声明的普通变量。

?? 运算符只检查 null 和未定义,不把 0、''、false 当成“空”来处理——这是它和 ?: 最关键的区别,用错就会 silently 覆盖合法值。
?? 用于安全取数组或超全局变量的值
从 $_GET、$_POST 或嵌套数组里取值时,传统写法要层层 isset(),容易漏判或写错层级。用 ?? 可直接链式兜底:
-
$id = $_GET['id'] ?? 0;—— 若$_GET['id']不存在或为null,返回0;但若值是字符串"0"或整数0,都会原样返回 -
$country = $user['address']['country'] ?? 'unknown';—— PHP 7+ 允许直接访问深层键,只要左侧表达式能解析(即使中间某层是null,也不会报Notice) - 错误示范:
$name = $_POST['name'] ?: 'guest';—— 若用户提交了空字符串或数字0,也会被替换成'guest',这不是你想要的
??= 是 ?? 的赋值简写,不是“或等于”
??= 不是逻辑运算符,而是赋值操作符,语义等价于 $a = $a ?? $b;,但它只在左侧为 null 或未定义时才执行右侧表达式:
-
$_SESSION['cart_id'] ??= uniqid('cart_');—— 首次访问生成 ID,后续不再覆盖 -
$config['timeout'] ??= 30;—— 若配置项没设置,才填默认值;已设为0或false都保留原值 - 注意:
$cache[$key] ??= expensiveQuery();中,expensiveQuery()仅在$cache[$key]为null或未定义时才调用,有短路效果
?? 和 ?: 混用时的优先级陷阱
?? 优先级低于三元运算符 ?:,混用不加括号会出意料之外的结果:
立即学习“PHP免费学习笔记(深入)”;
- 错误写法:
$x = $a ?? $b ?: $c;—— 实际等价于$x = ($a ?? $b) ?: $c;,即先??再整体做真假判断,$b是0或''就会触发$c - 正确写法:
$x = $a ?? ($b ?: $c);或更清晰地拆开:$x = $a ?? $b; $x = $x ?: $c; - PHP 8+ 支持
match表达式,复杂兜底建议改用match,避免嵌套??和?:带来的可读性问题
真正容易被忽略的是:?? 对“未定义索引”的容忍是语法层面的,但对“未定义变量”仍会触发 Notice(如 $undefined_var ?? 'default' 在严格模式下会报 Undefined variable)。所以它只安全用于已知结构的数组或超全局变量,别拿它去救一个根本没声明过的普通变量。



















