首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 獲取表單數據完整指南:$_GET、$_POST、$_REQUEST 差異、安全過濾與最佳實踐

     編輯:PHP 相關知識

三大超全局變量對比

變量來源適用場景安全性
$_GET URL 查詢字符串 ?key=val 搜尋、分頁、排序、幂等操作 可見、可被緩存、CSRF 風險低
$_POST HTTP Body(application/x-www-form-urlencoded / multipart/form-data) 表單提交、狀態變更、敏感數據 不在 URL 中、需配合 CSRF Token
$_REQUEST $_GET + $_POST + $_COOKIE(受 request_order 影響) 極少數兼容舊代碼場景 不推薦:來源模糊、Cookie 覆蓋風險

基本用法

<?php
// 獲取單個值(推薦過濾輸入)
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_SPECIAL_CHARS);
$age      = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
$tags     = filter_input(INPUT_POST, 'tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);

// 判斷是否提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 處理邏輯
}

表單元素對應獲取方式

HTML 元素name 屬性PHP 獲取代碼返回類型
<input type="text"> username $_POST['username'] string
<input type="password"> password $_POST['password'] string
<select> (單選) city $_POST['city'] string
<select multiple> cities[] $_POST['cities'] array
<input type="checkbox"> (多個同名) hobby[] $_POST['hobby'] array
<input type="radio"> (同名分組) gender $_POST['gender'] string (被選值)
<input type="file"> avatar $_FILES['avatar'] array (tmp_name, size, error...)

完整表單處理範例

<?php
// process.php
declare(strict_types=1);

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit('僅接受 POST 請求');
}

// 1. CSRF 驗證(簡化版)
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
    http_response_code(403);
    exit('CSRF 驗證失敗');
}

// 2. 定義驗證規則
$rules = [
    'username' => ['required' => true, 'filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'min' => 3, 'max' => 20],
    'email'    => ['required' => true, 'filter' => FILTER_VALIDATE_EMAIL],
    'age'      => ['required' => false, 'filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 120]],
    'hobby'    => ['required' => false, 'filter' => FILTER_DEFAULT, 'flags' => FILTER_REQUIRE_ARRAY],
    'gender'   => ['required' => true, 'filter' => FILTER_SANITIZE_SPECIAL_CHARS],
    'bio'      => ['required' => false, 'filter' => FILTER_SANITIZE_SPECIAL_CHARS],
];

// 3. 批量過濾驗證
$inputs = filter_input_array(INPUT_POST, array_column($rules, 'filter'));
$errors = [];

foreach ($rules as $field => $rule) {
    $value = $inputs[$field] ?? null;
    if ($rule['required'] && ($value === null || $value === '' || $value === false)) {
        $errors[$field] = '此欄位為必填';
        continue;
    }
    if ($value === false) { // FILTER_VALIDATE_* 失敗返回 false
        $errors[$field] = '格式不正確';
    }
    // 長度檢查
    if (isset($rule['min']) && mb_strlen($value) < $rule['min']) {
        $errors[$field] = "最少 {$rule['min']} 字符";
    }
    if (isset($rule['max']) && mb_strlen($value) > $rule['max']) {
        $errors[$field] = "最多 {$rule['max']} 字符";
    }
}

if ($errors) {
    // 返回錯誤(API 或重定向回表單攜帶錯誤)
    exit(json_encode(['code' => 422, 'errors' => $errors], JSON_UNESCAPED_UNICODE));
}

// 4. 業務處理(此處 $inputs 已為安全數據)
// $userId = User::create($inputs);
// 重定向防重複提交
header('Location: success.php');
exit;

HTML 表單模板(配合上述處理)

<form action="process.php" method="post" enctype="multipart/form-data" novalidate>
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); ?>">

    <div>
        <label>用戶名:<input type="text" name="username" required minlength="3" maxlength="20"></label>
    </div>
    <div>
        <label>郵箱:<input type="email" name="email" required></label>
    </div>
    <div>
        <label>年齡:<input type="number" name="age" min="1" max="120"></label>
    </div>
    <div>
        <label>性別:
            <input type="radio" name="gender" value="male" required> 男
            <input type="radio" name="gender" value="female"> 女
        </label>
    </div>
    <div>
        <label>愛好:
            <input type="checkbox" name="hobby[]" value="coding"> 编程
            <input type="checkbox" name="hobby[]" value="reading"> 閱讀
            <input type="checkbox" name="hobby[]" value="sports"> 運動
        </label>
    </div>
    <div>
        <label>簡介:<textarea name="bio" maxlength="500"></textarea></label>
    </div>
    <button type="submit">提交</button>
</form>

安全最佳實踐總結

  1. 永不信任輸入:所有 $_GET/$_POST 經 filter_input 或驗證器處理後再使用。
  2. 輸出轉義:HTML 上下文用 htmlspecialchars(),JS 用 json_encode(),SQL 用預處理語句。
  3. CSRF 保護:狀態改變操作必須驗證 Token。
  4. 文件上傳:驗證 MIME、副檔名、大小、掃描病毒、重命名存儲、禁用腳本執行權限。
  5. 最小權限原則:只獲取業務需要的字段,避免 $_REQUEST 或 extract($_POST)。

現代框架中的對應

  • Laravel: $request->validated() / FormRequest
  • Symfony: $form->handleRequest($request) + Validator 組件
  • ThinkPHP: Validate::check($data)
  • 原生 PHP: filter_input_array + 自定義驗證類(如本文範例)

掌握原生表單處理細節,能讓你在任何框架或無框架環境下編寫安全、健壯的輸入處理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved