將註冊流程中常見的輸入驗證邏輯封裝為可複用的 Check 靜態類,提供語意化方法名稱、統一回傳格式(通過回傳原值、失敗回傳 false),便於控制器層直接判斷並組合錯誤訊息。
<?php
/**
* 使用者輸入驗證工具類
* 所有方法:通過返回原值,失敗返回 false
*/
class Check
{
/**
* 使用者名稱:英數底線,3-16 字元
*/
public static function isUsername($argv) {
return preg_match('/^[a-zA-Z0-9_]{3,16}$/', $argv) ? $argv : false;
}
/**
* Email 格式驗證 (RFC 5322 簡化版,支援常見格式)
*/
public static function isEmail($argv) {
// 更嚴謹的正則:local-part@domain
$pattern = '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/';
return preg_match($pattern, $argv) ? $argv : false;
}
/**
* 兩值比較:$force=true 時嚴格比較 (===),否則鬆散比較 (==)
*/
public static function isSame($argvOne, $argvTwo, $force = false) {
return $force ? ($argvOne === $argvTwo) : ($argvOne == $argvTwo);
}
/**
* QQ 號碼:5-12 位數字,首位非 0
*/
public static function isQQ($argv) {
return preg_match('/^[1-9]\d{4,11}$/', $argv) ? $argv : false;
}
/**
* 中國大陸手機號:11 位,支援最新號段 (13/14/15/16/17/18/19 開頭)
*/
public static function isMobile($argv) {
return preg_match('/^1[3-9]\d{9}$/', $argv) ? $argv : false;
}
/**
* 座機號碼:區號(3-4碼)-號碼(7-8碼),可選分機
*/
public static function isTel($argv) {
return preg_match('/^0\d{2,3}-?\d{7,8}(-\d{1,4})?$/', $argv) ? $argv : false;
}
/**
* 暱稱:基本 XSS 字元過濾 + 長度限制 (2-20 字元)
* 實際專案建議配合 HTMLPurifier 或前端雙向過濾
*/
public static function isNickname($argv) {
// 禁止控制字元、腳本標籤、SQL 關鍵字等
if (preg_match('/[\x00-\x1F\x7F<>\'\"&;]|script|select|union|insert|update|delete/i', $argv)) {
return false;
}
$len = mb_strlen($argv, 'UTF-8');
return ($len >= 2 && $len <= 20) ? $argv : false;
}
/**
* 純中文檢測 (UTF-8)
*/
public static function isChinese($argv) {
return preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $argv) ? $argv : false;
}
/**
* 身分證字號 (台灣格式):1 英字 + 9 數字
*/
public static function isTwID($argv) {
if (!preg_match('/^[A-Z][12]\d{8}$/', $argv)) return false;
// 檢查碼驗算法
$letters = 'ABCDEFGHJKLMNPQRSTUVXYWZIO'; // 依序對應 10-35
$nums = [1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4];
$c1 = strpos($letters, $argv[0]);
$n1 = $nums[$c1];
$sum = (int)($n1 / 10) + ($n1 % 10) * 9;
for ($i = 1; $i <= 8; $i++) {
$sum += (int)$argv[$i] * (9 - $i);
}
$check = (10 - ($sum % 10)) % 10;
return $check == (int)$argv[9] ? $argv : false;
}
/**
* 統一編號 (台灣公司):8 位數字
*/
public static function isTwVAT($argv) {
if (!preg_match('/^\d{8}$/', $argv)) return false;
$weights = [1,2,1,2,1,2,4,1];
$sum = 0;
for ($i = 0; $i < 8; $i++) {
$p = (int)$argv[$i] * $weights[$i];
$sum += ($p >= 10) ? ($p - 9) : $p;
}
return ($sum % 10 === 0) ? $argv : false;
}
}
?>
<?php
require_once 'Check.php';
$errors = [];
$username = $_POST['username'] ?? '';
$email = $_POST['email'] ?? '';
$mobile = $_POST['mobile'] ?? '';
$pwd = $_POST['password'] ?? '';
$pwd2 = $_POST['password2'] ?? '';
// 驗證鏈
Check::isUsername($username) ?: $errors[] = '帳號格式錯誤 (英數底線 3-16 字)';
Check::isEmail($email) ?: $errors[] = '信箱格式不正確';
Check::isMobile($mobile) ?: $errors[] = '手機號碼格式錯誤';
Check::isSame($pwd, $pwd2, true) ?: $errors[] = '兩次密碼不一致';
strlen($pwd) >= 8 ?: $errors[] = '密碼至少 8 字元';
if ($errors) {
// 回傳 JSON 錯誤或重導表單帶入錯誤訊息
echo json_encode(['success' => false, 'errors' => $errors]);
exit;
}
// 全部通過,進行註冊邏輯...
?>
若專案已使用框架,**強烈建議直接使用框架內建驗證器**,支援:
unique:users,emailrequired_if:role,admin// Laravel 範例
$request->validate([
'username' => 'required|alpha_dash|size:3,16|unique:users',
'email' => 'required|email|unique:users',
'mobile' => ['required', 'regex:/^1[3-9]\d{9}$/'],
'password' => 'required|min:8|confirmed',
]);
自建驗證類適合輕量專案或無框架環境,核心原則:**白名單正則、統一回傳格式、集中管理規則**。隨專案增長,應平滑遷移至框架級驗證組件,獲得更完整的生態支援。