表單驗證核心在於「格式檢查」與「業務規則」。PHP 提供強大的 preg_match() 正則引擎與 filter_var() 內建過濾器,兩者互補,能精準驗證姓名、Email、URL 等常見欄位。
preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int|false
1 符合、0 不符合、false 錯誤$matches[0] 完整匹配、$matches[1] 第一個捕獲組.../pattern/, #pattern#, ~pattern~<?php
$name = trim($_POST['name'] ?? '');
if (!preg_match('/^[A-Za-z\s]+$/', $name)) {
$nameErr = '英文姓名僅允許字母與空格';
}
// 允許連字號、撇號(如 O'Connor, Jean-Paul)
if (!preg_match("/^[A-Za-z\s'-]+$/", $name)) { ... }
<?php
// 基本中文字符範圍 \u4e00-\u9fa5(CJK Unified Ideographs)
if (!preg_match('/^[\p{Han}A-Za-z\s]+$/u', $name)) {
$nameErr = '姓名僅允許中英文字母與空格';
}
// 更完整:支援擴展區、生僻字
if (!preg_match('/^[\p{Han}\p{L}\s]+$/u', $name)) { ... }
mb_strlen($name) <= 50!preg_match('/[\x00-\x1F\x7F]/', $name)preg_replace('/\s+/', ' ', $name)<?php
$email = trim($_POST['email'] ?? '');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = 'Email 格式不正確';
}
// 選項:禁止特定域名、要求特定 TLD
$options = [
'options' => ['regexp' => '/@(gmail|yahoo|outlook)\.com$/i']
];
// filter_var($email, FILTER_VALIDATE_EMAIL, $options); // PHP 8.1+
優點: 符合 RFC 5322/6531、支援國際化域名(IDN)、維護成本低。
<?php
// 簡易版(教學常見)
if (!preg_match('/^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$/', $email)) { ... }
// 較嚴格(RFC 5322 官方正則極其複雜,不建議手寫)
// 實務上 filter_var 足夠,特殊需求再加強:
// 1. 禁止臨時信箱域名
// 2. 要求公司域名
// 3. 長度限制
<?php
function validateEmailDeep($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$domain = substr(strrchr($email, '@'), 1);
// 檢查 MX 記錄
return checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A');
}
<?php
$url = trim($_POST['website'] ?? '');
if (!filter_var($url, FILTER_VALIDATE_URL)) {
$urlErr = 'URL 格式不正確(需含 https:// 或 https://)';
}
// 選項:限制 scheme、要求路徑、查詢字串
$options = [
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED,
'options' => ['regexp' => '/^https?:\/\//i'] // 僅允許 http/https
];
// filter_var($url, FILTER_VALIDATE_URL, $options);
<?php
// 允許 www. 開頭、支援子域名、連接埠、路徑、查詢、錨點
$pattern = '~^
(https?://)? # 選擇性 scheme
([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,} # 域名
(:\d{1,5})? # 選擇性 port
(/[^\s]*)? # 選擇性 path
(\?[^\s#]*)? # 選擇性 query
(\#[^\s]*)? # 選擇性 fragment
$~ix';
if (!preg_match($pattern, $url)) {
$urlErr = 'URL 格式不正確';
}
// 自動補全 scheme
if (!preg_match('~^https?://~i', $url)) {
$url = 'https://' . $url;
}
<?php
function validateUrlReachable($url, $timeout = 5) {
if (!filter_var($url, FILTER_VALIDATE_URL)) return false;
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_NOBODY => true, // HEAD 請求
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
]);
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode >= 200 && $httpCode < 400;
}
<?php
function validateForm(array $input): array {
$errors = [];
$clean = [];
// 姓名
$name = trim($input['name'] ?? '');
if ($name === '') {
$errors['name'] = '姓名必填';
} elseif (!preg_match('/^[\p{Han}\p{L}\s\'-]+$/u', $name)) {
$errors['name'] = '姓名包含非法字符';
} elseif (mb_strlen($name) > 50) {
$errors['name'] = '姓名過長';
} else {
$clean['name'] = $name;
}
// Email
$email = trim($input['email'] ?? '');
if ($email === '') {
$errors['email'] = 'Email 必填';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Email 格式錯誤';
} elseif (strlen($email) > 254) {
$errors['email'] = 'Email 過長';
} else {
$clean['email'] = strtolower($email);
}
// 網址(選填)
$url = trim($input['website'] ?? '');
if ($url !== '') {
if (!filter_var($url, FILTER_VALIDATE_URL, [
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
])) {
$errors['website'] = '請輸入完整網址(含 https:// 或 https://)';
} else {
$clean['website'] = $url;
}
}
return ['errors' => $errors, 'clean' => $clean];
}
// 使用
$result = validateForm($_POST);
if (empty($result['errors'])) {
$cleanData = $result['clean'];
// 儲存資料庫...
} else {
// 顯示錯誤...
}
?>
| 用途 | 模式 | 說明 |
|---|---|---|
| 手機號(台) | /^09\d{8}$/ | 09 開頭 10 碼 |
| 身分證字號 | /^[A-Z][12]\d{8}$/ | 字母+性別碼+8數字 |
| 統一編號 | /^\d{8}$/ | 8 位數字 |
| 郵遞區號(台) | /^\d{3,5}$/ | 3-5 碼 |
| IPv4 | /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)$/ | 標準 IPv4 |
| 十六進位顏色 | /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ | #RRGGBB 或 #RGB |
| 強密碼 | /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/ | 大小寫+數字+特殊符號 8+ |
x 修飾符(忽略空白、允許 # 註解)u 修飾符、\p{L} (任意字母)、\p{Han} (漢字)驗證不是「阻擋用戶」,而是「引導用戶輸入正確資料」。善用 PHP 內建過濾器處理標準格式,正則處理業務特定規則,並提供清晰錯誤訊息,是打造優質表單體驗的關鍵。