<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<title>用戶名檢測</title>
<style>
.msg { margin-left: 10px; font-size: 14px; }
.ok { color: green; } .err { color: red; }
</style>
</head><body>
<form id="regForm" action="register.php" method="post">
<label>用戶名:<input type="text" name="username" id="username" required></label>
<span id="userMsg" class="msg"></span><br><br>
<label>密碼:<input type="password" name="password" required></label><br><br>
<button type="submit">註冊</button>
</form>
<script>
const input = document.getElementById('username');
const msgEl = document.getElementById('userMsg');
let timer = null;
input.addEventListener('input', () => {
clearTimeout(timer);
timer = setTimeout(checkUser, 300); // 300ms 防抖
});
async function checkUser() {
const username = input.value.trim();
if (!username) { msgEl.textContent = ''; return; }
if (username.length < 3) { showMsg('至少 3 字符', 'err'); return; }
try {
const res = await fetch(`check_user.php?username=${encodeURIComponent(username)}`);
const data = await res.json();
if (data.available) {
showMsg('✓ 可用', 'ok');
} else {
showMsg('✗ ' + (data.msg || '已被註冊'), 'err');
}
} catch (e) {
showMsg('檢測失敗', 'err');
}
}
function showMsg(text, cls) {
msgEl.textContent = text;
msgEl.className = 'msg ' + cls;
}
// 表單提交前二次驗證
document.getElementById('regForm').addEventListener('submit', async (e) => {
const username = input.value.trim();
const res = await fetch(`check_user.php?username=${encodeURIComponent(username)}`);
const data = await res.json();
if (!data.available) {
e.preventDefault();
showMsg('✗ ' + (data.msg || '用戶名已存在'), 'err');
}
});
</script>
</body></html>
<?php
// check_user.php
require_once __DIR__ . '/config/db.php'; // 返回 PDO 實例
header('Content-Type: application/json; charset=UTF-8');
$username = trim($_GET['username'] ?? '');
if ($username === '') {
echo json_encode(['available' => false, 'msg' => '用戶名不能為空']);
exit;
}
// 基本格式校驗
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
echo json_encode(['available' => false, 'msg' => '格式錯誤:3-20 位字母數字下劃線']);
exit;
}
// 查詢數據庫
$stmt = $pdo->prepare('SELECT 1 FROM users WHERE username = ? LIMIT 1');
$stmt->execute([$username]);
$exists = $stmt->fetchColumn();
if ($exists) {
echo json_encode(['available' => false, 'msg' => '該用戶名已被註冊']);
} else {
echo json_encode(['available' => true]);
}
<?php
// config/db.php
$dsn = 'mysql:host=127.0.0.1;dbname=myapp;charset=utf8mb4';
$user = 'dbuser';
$pass = 'dbpass';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 真預處理
];
$pdo = new PDO($dsn, $user, $pass, $options);
return $pdo;
$('#username').on('blur', function() {
const val = $(this).val().trim();
if (!val) return;
$.getJSON('check_user.php', {username: val}, function(data) {
$('#userMsg').removeClass('ok err')
.text(data.available ? '✓ 可用' : '✗ ' + data.msg)
.addClass(data.available ? 'ok' : 'err');
});
});
「前端防抖 + 後端預處理 + JSON 響應 + 雙重驗證」是用戶名即時檢測的標準模式。核心在於**預處理語句防注入**、**格式校驗前置**、**併發安全**,而非單純的 AJAX 請求。