?? 运算符用于判断变量是否存在且不为 null,不触发 undefined notice;?: 判断值是否为真,会触发 notice 且将 0、'' 等 falsy 值视为假。

?: 会触发 undefined notice,?? 不会
当左侧变量未定义时,?: 会先尝试读取它,PHP 就抛出 Notice: Undefined variable;而 ?? 完全跳过读取,直接走右值分支。这不是“更安全”,是语义不同:前者判断“值是否为真”,后者判断“变量是否存在且不为 null”。
-
$a ?: 'default'等价于isset($a) && $a ? $a : 'default'—— 但前提是$a已声明 -
$a ?? 'default'等价于isset($a) ? $a : 'default'——$a可以完全没出现过 - 如果
$a = 0,$a ?: 'no'返回'no'(因为0是 falsy),但$a ?? 'no'返回0
嵌套使用 ?: 容易掉进逻辑坑里
写成 $a ?: $b ?: $c 看似简洁,实际是左结合:($a ?: $b) ?: $c。一旦 $a 是 0、false 或空字符串,就跳到 $b,再按同样规则判断 $b,最后才兜底 $c。这不是 fallback 链,是“找第一个 truthy 值”。
- 想表达“取第一个非 null 的变量”,该用
$a ?? $b ?? $c -
$a ?: $b ?: $c和$a ?? $b ?? $c在$a = ''时结果完全不同 - 混用(比如
$a ?: $b ?? $c)会因优先级引发歧义,PHP 7.4+ 虽支持,但可读性极差,建议加括号或拆行
?? 不能替代 isset() + empty() 组合判断
?? 只管 null 和未定义,对 ''、0、false 这些“存在但空”的值照单全收。如果你需要过滤掉空字符串,?? 无能为力。
-
$name ?? 'guest'在$name = ''时返回'',不是'guest' - 要同时排除 null 和空字符串,得写
($name !== null && $name !== '') ? $name : 'guest',或封装函数 -
??的右侧可以是任意表达式,包括函数调用,但要注意:它只在左侧为 null/undefined 时执行,不会提前求值
PHP 版本兼容性必须卡死 7.0+
?? 是 PHP 7.0 引入的,低版本直接报语法错误。线上环境若还跑着 PHP 5.6,硬上 ?? 会导致 fatal error,连错误页面都吐不出来。
立即学习“PHP免费学习笔记(深入)”;
- 检查版本用
php -v或PHP_VERSION_ID常量 - CI/CD 流水线里务必验证目标环境 PHP 版本,不能只看本地
- 升级到 PHP 7.4+ 后,
??支持链式($a ?? $b ?? $c)和与??=(空合并赋值)配合,但旧代码里??=在 7.4 才可用
真正容易被忽略的是:这两个运算符解决的根本不是同一类问题。?? 是“防未定义”,?: 是“选真值”。选错一个,可能让 0 消失、让空字符串意外透出、或者在日志里塞满 undefined notice。别凭感觉换,先想清楚你要拦截什么。










