为何empty()会抛出“Undefined Index”错误?
解决PHP三元运算符导致的Undefined Index错误
问题重现
我原本想用嵌套三元运算符依次检查$_SERVER里的几个请求来源字段,代码如下:
$origin = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : !empty($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : !empty($_SERVER['ORIGIN']) ? $_SERVER['ORIGIN'] : "Unknown Origin";
结果运行时抛出了错误:somePHPFile.php:40 出现Undefined index: ORIGIN
问题根源
一开始我有点困惑——毕竟empty()作为语言结构,明明会先检查键是否存在再判断值是否为空,怎么还会触发Undefined Index?后来才搞明白,问题出在PHP三元运算符的左结合性上。
PHP的三元运算符是左关联的,这意味着上面的代码会被PHP解析成这样的结构:
$origin = ((!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : !empty($_SERVER['HTTP_ORIGIN'])) ? $_SERVER['HTTP_ORIGIN'] : !empty($_SERVER['ORIGIN'])) ? $_SERVER['ORIGIN'] : "Unknown Origin";
这种解析顺序完全打乱了我们的预期:哪怕HTTP_REFERER存在且不为空,代码还是会继续去判断HTTP_ORIGIN的empty状态,甚至会直接访问$_SERVER['ORIGIN']——当这个键不存在时,自然就抛出了Undefined Index错误。
修复方案
我通过给每个嵌套的else分支添加括号,强制改变运算优先级,让代码按照我们想要的右关联逻辑执行:
$origin = (!empty($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : ((!empty($_SERVER['HTTP_ORIGIN'])) ? $_SERVER['HTTP_ORIGIN'] : (!empty($_SERVER['ORIGIN']) ? $_SERVER['ORIGIN'] : "Unbekannte Herkunft"));
添加括号后,代码会从右往左依次判断:只有当前面的字段不存在或为空时,才会去检查下一个字段,彻底避免了访问不存在的数组键。
额外补充
再啰嗦两句:empty()和isset()的区别在于,empty()会在键存在的情况下,进一步判断值是否为松散等价于false的内容(比如""、0、null等),而isset()只判断键是否存在且值不为null。但这次的问题和它们的功能差异无关,纯粹是三元运算符的解析顺序坑了人。
内容的提问来源于stack exchange,提问作者Toastgeraet
相关产品推荐
相关产品推荐

