empty(0) 返回 true 是设计如此,因 empty() 判定逻辑为 !$value(falsy 值均返回 true),包括 0、0.0、""、null、[] 和特例 "0";PHP 8.4 未改变该行为,与历史完全一致。

empty() 在 PHP 8.4 中判断 0 仍返回 true —— 这不是 bug,是设计如此,且与历史行为完全一致。PHP 8.4 并未修改 empty() 的语义,它依然遵循“值为 falsy 且非 null、非 unset”这一逻辑,而 0(整数零)、0.0(浮点零)、"0"(字符串"0")等都属于被判定为“空”的值。
为什么 empty(0) 是 true?
empty() 的判定逻辑本质是:!$value(即对值取逻辑非),但额外排除了未定义变量(undefined variable)导致的 warning。它不关心类型,只看“是否在布尔上下文中为 false”。
以下值在 PHP 中统一被视为 falsy,empty() 对它们全部返回 true:
-
""(空字符串) -
0(整数零) -
0.0(浮点零) falsenull-
[](空数组)
注意:"0" 是特例 —— 它是字符串,但 empty("0") 也返回 true,这是 PHP 历史遗留行为(字符串 "0" 被特殊处理为 falsy)。
立即学习“PHP免费学习笔记(深入)”;
empty() 和 == false、=== false 的区别
很多人误以为 empty() 等价于 === false,其实不然。它更接近 !$value,但有两点关键差异:
-
empty($x)对未定义变量$x不报 warning;而!$x或$x == false会触发Notice: Undefined variable -
empty()对字符串"0"返回true;而"0" == false也返回true(松散比较),但"0" === false是false
var_dump(empty(0)); // true
var_dump(0 == false); // true
var_dump(0 === false); // false
var_dump(empty("0")); // true
var_dump("0" == false); // true
var_dump("0" === false); // false
什么时候不该用 empty() 判断数字或字符串?
当你真正关心“是否为数值零”或“是否为非空字符串”,而非“是否 falsy”时,empty() 就会出错:
- 检查表单提交的数字字段是否为
0(比如“年龄填了 0”是有效输入)→ 改用isset($val) && is_int($val)或明确比较$val === 0 - 判断字符串是否为空(不含空格、不含 "0")→ 用
trim($str) === ""或strlen($str) === 0 - 区分
0、false、null、""→ 必须用严格比较或is_numeric()+is_string()等组合判断
常见翻车场景:
$count = 0;
if (empty($count)) {
echo "没有数据"; // 错!其实是“有 0 条数据”,不是“无数据”
}
PHP 8.4 有新变化吗?
没有。empty() 在 PHP 8.4 中的行为与 PHP 5.0 以来完全一致。PHP 8.4 引入的是 static return type、never 类型增强、更严格的类型推导等特性,但未触碰 empty() 的语义。官方 RFC 和变更日志中均无相关调整。
如果你在升级后发现逻辑异常,大概率是之前代码恰好依赖了某个边缘 case(比如靠 empty("0") 为 true 实现了某种过滤),而新环境其他改动(如错误报告级别提升、类型声明更严格)让问题暴露出来 —— 不是 empty() 变了,是你的假设错了。











