瀏覽器 (HTML Form) --HTTP POST/GET--> 伺服器 (PHP $_POST/$_GET) --> 業務邏輯 --> 回應 (HTML/JSON/Redirect)
<!-- form.html -->
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>表單元素示範</title>
</head>
<body>
<form method="post" action="handle.php">
<fieldset>
<legend>基本資料</legend>
<label>姓名:<input type="text" name="username" required></label><br>
<label>性別:
<input type="radio" name="gender" value="male"> 男
<input type="radio" name="gender" value="female"> 女
<input type="radio" name="gender" value="other"> 其他
</label><br>
</fieldset>
<fieldset>
<legend>興趣 (多選)</legend>
<label><input type="checkbox" name="hobbies[]" value="coding"> 程式設計</label>
<label><input type="checkbox" name="hobbies[]" value="reading"> 閱讀</label>
<label><input type="checkbox" name="hobbies[]" value="gaming"> 遊戲</label>
<label><input type="checkbox" name="hobbies[]" value="music"> 音樂</label>
</fieldset>
<fieldset>
<legend>技能等級 (單選下拉)</legend>
<select name="skill_level">
<option value="beginner">初學者</option>
<option value="intermediate">中級</option>
<option value="advanced">高級</option>
</select>
</fieldset>
<fieldset>
<legend>動作按鈕</legend>
<button type="submit" name="action" value="save_draft">存草稿</button>
<button type="submit" name="action" value="publish">發布</button>
<button type="submit" name="action" value="preview">預覽</button>
<button type="reset">重填</button>
</fieldset>
</form>
</body>
</html>
handle.php<?php
// handle.php
declare(strict_types=1);
header('Content-Type: text/html; charset=UTF-8');
// 1. 僅處理 POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('僅接受 POST 請求');
}
// 2. 取得並清理輸入
$username = trim($_POST['username'] ?? '');
$gender = $_POST['gender'] ?? '';
$hobbies = $_POST['hobbies'] ?? []; // 陣列
$skillLevel = $_POST['skill_level'] ?? '';
$action = $_POST['action'] ?? '';
// 3. 驗證規則
$errors = [];
if ($username === '') $errors[] = '姓名必填';
if (!in_array($gender, ['male', 'female', 'other'], true)) $errors[] = '性別無效';
if (!is_array($hobbies)) $hobbies = [];
if (!in_array($skillLevel, ['beginner', 'intermediate', 'advanced'], true)) $errors[] = '技能等級無效';
if (!in_array($action, ['save_draft', 'publish', 'preview'], true)) $errors[] = '未知動作';
// 4. 顯示錯誤或處理成功
if ($errors) {
echo '<h2>輸入錯誤:</h2><ul>';
foreach ($errors as $e) echo "<li>" . htmlspecialchars($e) . "</li>";
echo '</ul><a href="form.html">返回修正</a>';
exit;
}
// 5. 業務邏輯分派
match ($action) {
'save_draft' => saveDraft($username, $gender, $hobbies, $skillLevel),
'publish' => publish($username, $gender, $hobbies, $skillLevel),
'preview' => preview($username, $gender, $hobbies, $skillLevel),
};
function saveDraft(string $name, string $gender, array $hobbies, string $level): void
{
// 儲存草稿邏輯 (資料庫、Session、檔案...)
echo "<h2>草稿已儲存</h2>";
displayData($name, $gender, $hobbies, $level);
}
function publish(string $name, string $gender, array $hobbies, string $level): void
{
// 發布邏輯
echo "<h2>發布成功!</h2>";
displayData($name, $gender, $hobbies, $level);
}
function preview(string $name, string $gender, array $hobbies, string $level): void
{
echo "<h2>預覽模式</h2>";
displayData($name, $gender, $hobbies, $level);
}
function displayData(string $name, string $gender, array $hobbies, string $level): void
{
echo "<pre>";
echo "姓名:" . htmlspecialchars($name) . "\n";
echo "性別:" . htmlspecialchars($gender) . "\n";
echo "興趣:" . htmlspecialchars(implode(', ', $hobbies)) . "\n";
echo "等級:" . htmlspecialchars($level) . "\n";
echo "</pre>";
}
<script>
document.querySelector('form').addEventListener('submit', function(e) {
const form = this;
// HTML5 原生驗證 (required, type=email, pattern...)
if (!form.checkValidity()) {
form.reportValidity(); // 顯示瀏覽器內建提示
e.preventDefault();
return;
}
// 自訂:至少勾選一個興趣
const hobbies = form.querySelectorAll('input[name="hobbies[]"]:checked');
if (hobbies.length === 0) {
alert('請至少選擇一項興趣');
e.preventDefault();
}
});
</script>
| 風險 | 防禦措施 |
|---|---|
| CSRF (跨站請求偽造) | 表單加入 ``,後端驗證 |
| XSS (跨站腳本) | 輸出時 `htmlspecialchars($var, ENT_QUOTES, 'UTF-8')` |
| SQL Injection | **永遠使用參數化查詢 (PDO prepared statements)** |
| 檔案上傳攻擊 | 驗證 MIME、重新命名、儲存於非公開目錄、禁止執行權限 |
| 重複提交 | POST-Redirect-GET 模式、前端提交後禁用按鈕、後端冪等性 Token |
表單處理是 Web 開發核心。掌握 `$_POST` 存取規則、驗證流程、安全防護、PRG 模式,並善用 HTML5 原生驗證輔助前端體驗,即能建構健壯的資料輸入介面。