isset() 與 empty() 是 PHP 最常用的變量狀態檢測函數,但語義差異導致大量邏輯 Bug。本文用真值表、源碼邏輯、實戰場景徹底釐清。
核心定義
- isset():變量**已聲明** 且 **不等於 null** →
true
- empty():變量**不存在** 或 **等於 false**(空值) →
true
完整真值表
| 變量狀態 | 代碼示例 | isset() | empty() | 備註 |
| 未定義 | $a; (無此行) | false | true | empty 不觸發警告 |
| null | $a = null; | false | true | |
| 空字符串 | $a = ''; | true | true | |
| 整數 0 | $a = 0; | true | true | |
| 浮點 0.0 | $a = 0.0; | true | true | |
| 字符串 "0" | $a = '0'; | true | true | 字符串 "0" 視為假值 |
| 布爾 false | $a = false; | true | true | |
| 空數組 | $a = []; | true | true | |
| 非空字符串 | $a = 'foo'; | true | false | |
| 非零數字 | $a = 1; | true | false | |
| 非空數組 | $a = [1]; | true | false | |
| 對象 | $a = new StdClass(); | true | false | |
| 資源 | $a = fopen(...); | true | false | |
底層邏輯等價代碼
function my_isset($var) {
return array_key_exists('var', get_defined_vars()) && $var !== null;
// 實際為 Zend VM 專用指令 ISSET_ISEMPTY_VAR,非用戶函數可模擬
}
function my_empty($var) {
// 等價於 !$var,但不觸發 "Undefined variable" 警告
return !isset($var) || !$var;
}
實戰選擇指南
| 場景 | 推薦 | 理由 |
| 檢測 $_GET/$_POST 是否提交 | isset($_POST['key']) | 區分「未提交」與「提交空值」 |
| 檢測配置項是否啟用 | !empty($config['flag']) | 未配置、false、0、'' 視同關閉 |
| 檢測數組鍵是否存在 | array_key_exists('key', $arr) | isset 對 null 值鍵返回 false |
| 檢測對象屬性 | property_exists($obj, 'prop') | 區分未聲明、聲明為 null、魔術 __get |
| 鏈式安全取值 | $a?->b?->c ?? 'default' (PHP 8) | Nullsafe 操作符 + 空合並運算符 |
常見陷阱
empty($obj->prop) 會觸發 __get('prop'),若返回 null 則 true,可能非預期
isset($arr['key']) 對 $arr['key'] = null 返回 false,用 array_key_exists 區分
empty() 不接受表達式:empty(trim($str)) 報錯,需用中間變量
原文代碼示例簡潔準確:isset($var) 未定義 false、定義空串 true;empty($var) 空串 true、'111' false。掌握真值表即可無腦套用。