首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP + AJAX 實現用戶名即時檢測(防重複註冊)

     編輯:PHP 相關知識

交互流程

  1. 用戶輸入用戶名,失焦(`blur`)或輸入延遲(`debounce`)觸發 AJAX 請求
  2. 前端發送 `GET /check_user.php?username=xxx`
  3. 後端查詢數據庫,返回 JSON:`{"available": true}` 或 `{"available": false, "msg": "已被註冊"}`
  4. 前端根據結果顯示綠色「可用」/ 紅色「已存在」提示
  5. 表單提交時再次服務端驗證(防繞過前端)

前端實現(原生 JS / Fetch API)

<!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;

安全加固

  • 限流:同一 IP 分鐘請求超過 30 次返回 429,防止遍歷用戶名庫。
  • 緩存:熱門用戶名查詢結果存入 Redis 1 分鐘,減輕 DB 壓力。
  • 註冊時事務鎖:`INSERT ... ON DUPLICATE KEY UPDATE` 或 `SELECT ... FOR UPDATE` 保證併發下不重複。
  • 用戶名規範:禁止敏感詞、純數字、過長過短,前後端雙重校驗。

進階:jQuery 版本(兼容老項目)

$('#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 請求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved