表單處理是 Web 開發最基礎的功能之一。PHP 透過超全域變數 $_GET、$_POST、$_REQUEST 接收客戶端提交的資料。本文詳細說明三者差異、使用時機、安全處理與完整實戰範例。
| HTTP Method | PHP 變數 | 資料位置 | 適用場景 | 資料長度限制 |
|---|---|---|---|---|
| GET | $_GET | URL 查詢字串 | 搜尋、分頁、篩選、可分享連結 | ~2000 字元(瀏覽器/伺服器限制) |
| POST | $_POST | 請求主體 | 登入、註冊、資料異動、檔案上傳、敏感資訊 | 受 post_max_size 限制(預設 8MB) |
| GET/POST | $_REQUEST | 兩者合併 | 不建議使用(來源不明、安全風險) | 同上 |
<form action="search.php" method="get">
<label>關鍵字:<input type="text" name="keyword" /></label>
<label>分類:
<select name="category">
<option value="">全部</option>
<option value="tech">科技</option>
<option value="life">生活</option>
</select>
</label>
<button type="submit">搜尋</button>
</form>
<!-- 提交後 URL:search.php?keyword=php&category=tech -->
<form action="register.php" method="post" enctype="multipart/form-data">
<label>帳號:<input type="text" name="username" required /></label>
<label>密碼:<input type="password" name="password" required /></label>
<label>大頭照:<input type="file" name="avatar" accept="image/*" /></label>
<button type="submit">註冊</button>
</form>
<?php
// search.php
$keyword = $_GET['keyword'] ?? '';
$category = $_GET['category'] ?? 'all';
// 安全處理:輸出時轉義,防止 XSS
$safeKeyword = htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');
echo "搜尋關鍵字:$safeKeyword";
?>
<?php
// register.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
// 驗證
$errors = [];
if ($username === '') $errors[] = '帳號不可為空';
if (strlen($password) < 8) $errors[] = '密碼至少 8 字元';
if (empty($errors)) {
// 雜湊密碼、寫入資料庫...
echo '註冊成功';
} else {
echo '錯誤:' . implode('、', $errors);
}
}
?>
<?php
// 明確指定來源,避免使用 $_REQUEST
$page = $_GET['page'] ?? 1; // 分頁參數通常在 URL
$action = $_POST['action'] ?? ''; // 異動操作通常用 POST
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? ''; // API 金鑰從 Header 取得
?>
| HTML 欄位 | name 屬性 | PHP 取值方式 | 備註 |
|---|---|---|---|
<input type="text"> | username | $_POST['username'] | 字串 |
<input type="checkbox"> | agree | isset($_POST['agree']) | 未勾選時不會送出,用 isset 判斷 |
<input type="checkbox"> 多個 | skills[] | $_POST['skills'] 為陣列 | 名稱加 [] 讓 PHP 自動解析為陣列 |
<input type="radio"> | gender | $_POST['gender'] | 同 name 群組,只會送出被選中的值 |
<select> 單選 | city | $_POST['city'] | 值為 option 的 value |
<select multiple> | cities[] | $_POST['cities'] 為陣列 | 名稱加 [] |
<textarea> | content | $_POST['content'] | 含換行字元 |
<input type="file"> | avatar | $_FILES['avatar'] | 參考 $_FILES 結構 |
htmlspecialchars($str, ENT_QUOTES, 'UTF-8') 防 XSS<input type="hidden" name="csrf_token" value="...">,驗證 Session 中的 token<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>留言板</title></head>
<body>
<form action="submit.php" method="post">
<label>暱稱:<input type="text" name="nickname" maxlength="20" required /></label><br>
<label>內容:<textarea name="content" rows="5" cols="40" required></textarea></label><br>
<label><input type="checkbox" name="subscribe" value="1" /> 訂閱回覆通知</label><br>
<button type="submit">送出留言</button>
</form>
</body></html>
<?php
session_start();
function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); }
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method Not Allowed');
}
// CSRF 驗證
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
http_response_code(403);
exit('CSRF token 無效');
}
$nickname = trim($_POST['nickname'] ?? '');
$content = trim($_POST['content'] ?? '');
$subscribe = isset($_POST['subscribe']);
$errors = [];
if ($nickname === '') $errors[] = '暱稱不可為空';
if (mb_strlen($nickname) > 20) $errors[] = '暱稱不可超過 20 字元';
if ($content === '') $errors[] = '內容不可為空';
if (!empty($errors)) {
echo '<ul><li>' . implode('</li><li>', array_map('h', $errors)) . '</li></ul>';
echo '<a href="form.html">返回修正</a>';
exit;
}
// 資料庫寫入(示意 PDO)
/*
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass');
$stmt = $pdo->prepare('INSERT INTO messages (nickname, content, subscribe, created_at) VALUES (?, ?, ?, NOW())');
$stmt->execute([$nickname, $content, $subscribe ? 1 : 0]);
*/
echo '留言送出成功!<a href="form.html">繼續留言</a>';
?>
enctype 是否正確(檔案上傳需 multipart/form-data)、post_max_size 是否過小、PHP 是否載入 php.ini 正確。$_POST['key'] ?? '' 或 isset($_POST['key']) 先判斷存在性。<meta charset="utf-8">、PHP 檔案儲存為 UTF-8、資料庫連線 SET NAMES utf8mb4。掌握 $_GET、$_POST 的差異與適用場景,明確指定資料來源,配合嚴格的輸入驗證與輸出轉義,是建構安全 PHP 表單處理的核心。拒絕使用 $_REQUEST,讓資料流向清晰可控。