isset() 判断变量是否存在(非null且已定义),empty() 判断值是否语义为空(如0、""、false、[]等均视为空);二者用途不同,不可混用。
这是最本质的区别:一个管存在性,一个管语义空值。比如 $a = 0,isset($a) 返回 true(变量已定义、非 null),但 empty($a) 也返回 true(0 被认为是“空”)。初学者常以为“设了值就一定不空”,结果表单里用户真输入了数字 0,用 empty() 一判,直接当没填——这就是踩坑起点。
isset() 只拒绝 null 和未定义变量;0、false、""、[] 全部通过empty() 把 0、"0"、false、null、""、[]、未定义变量,统统当“空”isset($x) → false,empty($x) → true,且都不报 warning" "(含空格字符串):isset() 为 true,empty() 为 false —— 它不是空字符串,只是看着“空”用户提交 age=0(比如新生儿)、price="0"、active="0",这些是合法业务值,但 empty($_POST['age']) 会误判为“没填”。这时候该用 isset() + 显式类型判断:
if (isset($_POST['age']) && is_numeric($_POST['age'])) {
$age = (int)$_POST['age'];
} else {
// 处理缺失或非法输入
}
isset()
!empty() 要谨慎,优先改用 strlen(trim($val)) > 0 或正则/类型检查"0" 字符串是个经典陷阱:empty("0") === true,但它是有效字符串,不能等同于未填写想确认 $_GET['id'] 是否传了,写 if (!empty($_GET['id'])) 看似省事,但如果 URL 是 ?id=0,逻辑就崩了。正确姿势是:
if (isset($_GET['id']) && $_GET['id'] !== '') {
// id 存在且非空字符串(再按需转 int 或校验格式)
}
empty($arr['key']) 在键不存在时返回 true,但也会在 $arr['key'] = 0 时返回 true —— 你根本分不清是“没传”,还是“传了零”isset($arr['key']) 才能干净区分“键不存在” vs “键存在但值为 null/0/false/''”$id = $_GET['id'] ?? null;,比 isset() 更简洁,但语义相同(只关心存在性)新版 PHP 允许 empty($a . $b) 或 empty(foo()),看起来灵活,但实际埋雷:
empty() 的“空”判断本不该触发业务逻辑null 或 false,empty() 仍会返回 true —— 可读
$val = foo(); if ($val !== '' && $val !== 0) { ... }
真正容易被忽略的点是:这两个函数不是互斥替代品,而是分工明确的工具。用错一个,轻则逻辑错漏,重则绕过权限校验(比如 if (!empty($user->role)) 把 role='guest' 当空跳过)。写之前,先问自己一句:我要确认的是“它有没有”,还是“它有没有用”。