??只响应null和未定义,对false、0、''、[]等falsy值原样返回;?:则将所有falsy值(含未定义变量,会触发notice)视为假并走右侧分支;两者语义不同,不可混用。

?? 运算符只响应 null 和未定义,完全不判断 false
?? 的设计目标非常明确:仅当左侧操作数为 null 或**未声明变量**时,才返回右侧默认值。它对 false、0、''、[] 等所有 falsy 值一律放行,不做任何转换或拦截。
常见错误现象:你传入 false 却期望它被当作“空”处理,结果代码逻辑跳过了默认分支——这不是 bug,是 ?? 的正确行为。
-
$status = false ?? 'pending';→ 返回false(不是'pending') -
$count = 0 ?? 1;→ 返回0(不是1) -
$name = '' ?? 'guest';→ 返回''(不是'guest')
什么时候该用 ?: 而不是 ??
当你需要把 false、0、'' 都视作“无效值”并触发默认逻辑时,?: 才是合适选择。但它有硬性前提:左侧变量必须已声明,否则直接抛出 Notice: Undefined variable。
使用场景举例:
- API 返回状态码为
0表示失败,你想 fallback 到默认提示:$msg = $api_result ?: 'Unknown error'; - 表单字段允许值为
false(如开关关闭),但你希望没提交时显示提示:isset($form['active']) ? $form['active'] : true更安全;若强行用?:,得先确保$form['active']已存在 -
?:在模板中快速兜底(如$user->name ?: 'Anonymous'),前提是$user->name不可能为null且你接受0或false被覆盖
混用 ?? 和 ?: 容易踩的优先级坑
?? 优先级高于 ?:,这意味着 $a ?: $b ?? $c 实际等价于 $a ?: ($b ?? $c),而不是 ($a ?: $b) ?? $c。这种隐式分组极易导致逻辑与预期相反。
正确写法必须显式加括号:
- 想取第一个“非 null”的值:
($a ?? $b) ?? $c - 想取第一个“非 falsy”的值:
($a ?: $b) ?: $c - 想取“非 null 且非空字符串”:
(isset($a) && $a !== '') ? $a : 'default',别试图用??和?:混合模拟
??= 赋值运算符不会误覆盖合法 falsy 值
??= 是 ?? 的赋值变体,只在左侧为 null 或未定义时才写入。它和 ||= 的关键区别就在这里:||= 会把 0、false 当作假值覆盖,而 ??= 完全无视它们。
典型误用对比:
-
$config['timeout'] ||= 3000;→ 若$config['timeout'] = 0,会被覆盖成3000(错误!0 是合法超时) -
$config['timeout'] ??= 3000;→0保留,只有null或未设置时才赋值(正确)
真正容易被忽略的是:线上环境若运行 PHP ?? 和 ??= 会直接报 Fatal error,连错误页面都吐不出来——检查 phpversion() 不能只看本地,得确认部署环境真实版本。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











