PHP 5.2 引入 **Filter 擴充套件**,提供 filter_input()、filter_var() 等原生函數,**無需撰寫正則即可完成常見輸入驗證/過濾**。本文詳細說明 filter_input() 語法、輸入來源常數、過濾器/驗證器旗標、實戰範例與**已知陷阱**(布林驗證行為),助你建構安全、可維護的輸入處理層。
filter_input(int $type, string $var_name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed
$type:輸入來源常數(見下表)。$var_name:變數名稱(如 'email')。$filter:過濾器/驗證器 ID(見下表)。$options:旗標陣列或位元組合(如 FILTER_FLAG_STRIP_HIGH)。false(驗證失敗)、null(變數不存在)。| 常數 | 對應超全域變數 | 說明 |
|---|---|---|
| INPUT_GET | $_GET | 查詢字串參數 |
| INPUT_POST | $_POST | POST 表單資料 |
| INPUT_COOKIE | $_COOKIE | Cookie |
| INPUT_SERVER | $_SERVER | 伺服器/執行環境資訊 |
| INPUT_ENV | $_ENV | 環境變數 |
| 分類 | 常數 | 用途 | 典型旗標 |
|---|---|---|---|
| 驗證 | FILTER_VALIDATE_INT | 整數驗證 | min_range, max_range |
| FILTER_VALIDATE_FLOAT | 浮點數驗證 | decimal, min_range, max_range | |
| FILTER_VALIDATE_EMAIL | Email 格式驗證 | FILTER_FLAG_EMAIL_UNICODE | |
| FILTER_VALIDATE_URL | URL 格式驗證 | FILTER_FLAG_PATH_REQUIRED, QUERY_REQUIRED | |
| FILTER_VALIDATE_IP | IP 驗證 | FILTER_FLAG_IPV4, IPV6, NO_PRIV_RANGE, NO_RES_RANGE | |
| FILTER_VALIDATE_BOOLEAN | 布林驗證 (見陷阱) | FILTER_NULL_ON_FAILURE | |
| FILTER_VALIDATE_REGEXP | 自訂正則驗證 | regexp | |
| 過濾 | FILTER_SANITIZE_STRING | 移除標籤、編碼特殊字元 (PHP 8.1 棄用,改用 htmlspecialchars) | FILTER_FLAG_STRIP_LOW, STRIP_HIGH, ENCODE_LOW, ENCODE_HIGH |
| FILTER_SANITIZE_EMAIL | 移除非法 Email 字元 | ||
| FILTER_SANITIZE_URL | 移除非法 URL 字元 | ||
| FILTER_SANITIZE_NUMBER_INT | 只保留數字、正負號 | ||
| FILTER_SANITIZE_NUMBER_FLOAT | 保留數字、小數點、指數符號 | FILTER_FLAG_ALLOW_FRACTION, ALLOW_THOUSAND, ALLOW_SCIENTIFIC | |
| FILTER_SANITIZE_FULL_SPECIAL_CHARS | HTML 實體編碼 (等同 htmlspecialchars ENT_QUOTES) |
<?php
// 1. 取得並驗證整數 ID (1~1000)
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, [
'options' => ['min_range' => 1, 'max_range' => 1000]
]);
if ($id === false || $id === null) {
die('無效 ID');
}
// 2. 取得並過濾 Email
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die('Email 格式錯誤');
}
// 3. 批次處理表單 (搭配 filter_input_array)
$filters = [
'username' => FILTER_SANITIZE_STRING,
'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range'=>18]],
'email' => FILTER_VALIDATE_EMAIL,
'tags' => ['filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_REQUIRE_ARRAY],
];
$data = filter_input_array(INPUT_POST, $filters);
// $data['age'] 可能為 false/null,需額外檢查
var_dump(filter_var('abc', FILTER_VALIDATE_BOOLEAN)); // bool(false)
var_dump(filter_var('0', FILTER_VALIDATE_BOOLEAN)); // bool(false) <-- 字串 "0" 視為 false
var_dump(filter_var('1', FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var('on', FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var('yes', FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var('', FILTER_VALIDATE_BOOLEAN)); // bool(false)
陷阱:字串 "0" 被視為 false,**但 "false" 字串卻回傳 true**(非空字串預設真)。若需嚴格 "true"/"false" 對應,請自訂驗證或使用 FILTER_VALIDATE_REGEXP。
| 場景 | 推薦函數 | 理由 |
|---|---|---|
| 直接從超全域變數取得並驗證 | filter_input() | 來源明確、不受變數覆蓋影響、可偵測變數是否存在 | 已有變數值(如經處理後)需再次驗證 | filter_var() | 輸入靈活、可對任意字串/變數操作 |
| 批次處理整個 $_POST/$_GET | filter_input_array() | 單次呼叫定義規則陣列、回傳結構化結果 |
filter_input_array 為 Request::validated(),集中管理規則。FILTER_SANITIZE_STRING 已棄用,**改用 htmlspecialchars()** 或 FILTER_SANITIZE_FULL_SPECIAL_CHARS。善用 filter_input() 可消除大量手寫正則與 isset/empty 判斷,建立**宣告式、可測試、安全**的輸入邊界。