PHP 為動態弱型別語言,變數型別由值決定。準確檢測型別是防禦性程式設計的關鍵。
<?php
$vars = [
'string' => "hello",
'integer' => 42,
'float' => 3.14,
'boolean' => true,
'array' => [1, 2, 3],
'object' => new stdClass(),
'resource' => fopen('php://memory', 'r'),
'NULL' => null,
'unknown' => new class {} // 匿名類別
];
foreach ($vars as $name => $var) {
echo "{$name}: " . gettype($var) . "\n";
}
/*
輸出:
string: string
integer: integer
float: double ← 注意:float 回傳 "double"
boolean: boolean
array: array
object: object
resource: resource
NULL: NULL
unknown: object
*/
?>
注意事項:
"double" 而非 "float"(歷史原因)gettype() 仍回傳 "resource"| 函數 | 檢測型別 | 等價判斷 |
|---|---|---|
is_int() / is_integer() / is_long() | 整數 | gettype($v) === 'integer' |
is_float() / is_double() / is_real() | 浮點數 | gettype($v) === 'double' |
is_bool() | 布林值 | gettype($v) === 'boolean' |
is_string() | 字串 | gettype($v) === 'string' |
is_array() | 陣列 | gettype($v) === 'array' |
is_object() | 物件 | gettype($v) === 'object' |
is_resource() | 資源 | gettype($v) === 'resource' |
is_null() | NULL | gettype($v) === 'NULL' |
is_scalar() | 純量型別 | int/float/bool/string |
is_callable() | 可呼叫 | 函數、Closure、__invoke 物件 |
is_iterable() | 可迭代 | 陣列、Traversable 物件(PHP 7.1+) |
is_numeric() | 數字字串 | "123", "1.5", "0xFF" |
<?php
$testCases = [
'undefined' => null, // 未定義變數
'null' => null,
'empty_string' => '',
'zero_int' => 0,
'zero_float' => 0.0,
'zero_string' => '0',
'false_bool' => false,
'empty_array' => [],
'string' => 'hello',
'int' => 42,
];
echo "變數名\t\tisset\tempty\tis_null\n";
foreach ($testCases as $name => $value) {
// 注意:isset() 需直接傳變數,不可傳運算式
// 這裡用變數變數模擬
$$name = $value;
$i = isset($$name) ? 'T' : 'F';
$e = empty($$name) ? 'T' : 'F';
$n = is_null($$name) ? 'T' : 'F';
echo "{$name}\t{$i}\t{$e}\t{$n}\n";
}
/*
輸出:
變數名 isset empty is_null
undefined F T T (注意:isset 未定義變數不報錯)
null F T T
empty_string T T F
zero_int T T F
zero_float T T F
zero_string T T F
false_bool T T F
empty_array T T F
string T F F
int T F F
*/
?>
| 函數 | 未定義 | null | 0/''/false/[] | 有值 |
|---|---|---|---|---|
isset() | F | F | T | T |
empty() | T | T | T | F |
is_null() | T (警告) | T | F | F |
=== null | T (警告) | T | F | F |
<?php
// 1. 檢查陣列鍵是否存在且非 null
function getArrayValue(array $arr, string $key, $default = null) {
return array_key_exists($key, $arr) ? $arr[$key] : $default;
// 或 PHP 7.0+: return $arr[$key] ?? $default; // 但 null 值也會回傳 default
}
// 2. 嚴格型別檢查(避免 "123" 通過 is_int)
function requireInt($value, string $paramName) {
if (!is_int($value)) {
throw new InvalidArgumentException("參數 {$paramName} 必須為整數,收到 " . gettype($value));
}
}
// 3. 數字字串轉換與驗證
function parsePositiveInt($input) {
if (!is_numeric($input)) return false;
$val = (int)$input;
return $val > 0 && (string)$val === (string)$input ? $val : false; // 拒絕 "123abc"
}
// 4. 型別斷言(PHPStan/Psalm 靜態分析用)
/** @var string|int $mixed */
/** @assert $mixed !== null */
function process($mixed) {
if (is_string($mixed)) {
// $mixed 在此為 string
} elseif (is_int($mixed)) {
// $mixed 在此為 int
}
}
?>
is_*() 函數為內建 opcode,執行速度極快。gettype() 需分配回傳字串,較慢約 3-5 倍。邏輯判斷務必使用 is_*()。