萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> 程式語言綜合

AJAX 表單提交入庫完整流程 (PHP + jQuery + MySQLi)

架構概覽

  • 前端:HTML5 表單 + jQuery 3.x 驗證與 AJAX 提交
  • 後端:PHP 7+ + MySQLi (Prepared Statement 防注入)
  • 資料交換:JSON 格式
  • 安全:輸入驗證、參數化查詢、XSS 過濾、CSRF Token (建議補充)

前端頁面 (index.html)

<!DOCTYPE html>
<html lang="zh-TW">
<head>
  <meta charset="UTF-8">
  <title>會員註冊 - AJAX 示範</title>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body {font-family: "Microsoft JhengHei", sans-serif; text-align:center; padding-top:50px;}
    .form-box {display:inline-block; text-align:left; border:1px solid #ddd; padding:20px; border-radius:8px; box-shadow:0 2px 6px rgba(0,0,0,.1);}
    .form-row {margin-bottom:15px;}
    label {display:inline-block; width:100px; text-align:right; margin-right:10px; font-weight:bold;}
    input[type=text], input[type=password], input[type=email] {padding:8px; border:1px solid #ccc; border-radius:4px; width:250px;}
    .btn {padding:10px 24px; background:#007bff; color:#fff; border:none; border-radius:4px; cursor:pointer; font-size:16px;}
    .btn:hover {background:#0056b3;}
    .msg {margin-top:15px; font-weight:bold;}
    .error {color:#dc3545;} .success {color:#28a745;}
    .loading {color:#6c757d;}
  </style>
</head>
<body>
  <div class="form-box">
    <h2>會員註冊</h2>
    <form id="regForm">
      <div class="form-row">
        <label>帳號:</label>
        <input type="text" id="username" name="username" required>
      </div>
      <div class="form-row">
        <label>年齡:</label>
        <input type="number" id="age" name="age" min="1" max="120" required>
      </div>
      <div class="form-row">
        <label>密碼:</label>
        <input type="password" id="password" name="password" minlength="6" maxlength="20" required>
      </div>
      <div class="form-row">
        <label>地址:</label>
        <input type="text" id="address" name="address" required>
      </div>
      <div class="form-row">
        <label>Email:</label>
        <input type="email" id="email" name="email" required>
      </div>
      <div class="form-row">
        <button type="submit" class="btn">註冊</button>
        <button type="reset" class="btn" style="background:#6c757d;">重置</button>
      </div>
    </form>
    <div id="result" class="msg"></div>
    <div id="loading" class="msg loading" style="display:none;">處理中...</div>
  </div>

  <script>
  $(function(){
    $('#regForm').on('submit', function(e){
      e.preventDefault();
      var $form = $(this), $btn = $form.find('button[type=submit]'), $msg = $('#result'), $loading = $('#loading');

      // 前端驗證
      var username = $.trim($('#username').val());
      var age = $.trim($('#age').val());
      var password = $.trim($('#password').val());
      var address = $.trim($('#address').val());
      var email = $.trim($('#email').val());

      if(!username){ alert('請輸入帳號'); return; }
      if(!age || !/^\d+$/.test(age)){ alert('請輸入有效年齡'); return; }
      if(password.length < 6 || password.length > 20){ alert('密碼長度 6-20 字元'); return; }
      if(!address){ alert('請輸入地址'); return; }
      if(!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)){ alert('Email 格式錯誤'); return; }

      $btn.prop('disabled', true);
      $loading.show();
      $msg.removeClass('error success').text('');

      $.ajax({
        url: '_process.php',
        type: 'POST',
        dataType: 'json',
        data: {
          username: username,
          age: age,
          password: password,
          address: address,
          email: email
        },
        success: function(res){
          $loading.hide();
          $btn.prop('disabled', false);
          if(res.success){
            $msg.addClass('success').text(res.message);
            $form[0].reset();
          }else{
            $msg.addClass('error').text(res.message);
          }
        },
        error: function(xhr){
          $loading.hide();
          $btn.prop('disabled', false);
          $msg.addClass('error').text('伺服器錯誤:' + xhr.status);
        }
      });
    });
  });
  </script>
</body>
</html>

後端處理 (_process.php)

<?php
header('Content-Type: application/json; charset=utf-8');

// 資料庫連線 (建議改用環境變數/設定檔管理憑證)
$mysqli = new mysqli('localhost', 'root', 'root', 'register');
if ($mysqli->connect_errno) {
    echo json_encode(['success'=>false, 'message'=>'資料庫連線失敗: '.$mysqli->connect_error]);
    exit;
}
$mysqli->set_charset('utf8mb4');

// 接收並清理輸入
$username = trim($_POST['username'] ?? '');
$age      = isset($_POST['age']) ? (int)$_POST['age'] : 0;
$password = trim($_POST['password'] ?? '');
$address  = trim($_POST['address'] ?? '');
$email    = trim($_POST['email'] ?? '');

// 伺服端二次驗證
$errors = [];
if ($username === '') $errors[] = '帳號不可為空';
if ($age <= 0) $errors[] = '年齡需為正整數';
if ($password === '') $errors[] = '密碼不可為空';
if ($address === '') $errors[] = '地址不可為空';
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Email 格式錯誤';

if ($errors) {
    echo json_encode(['success'=>false, 'message'=>implode(';', $errors)]);
    exit;
}

// 檢查帳號唯一性
$stmt = $mysqli->prepare("SELECT 1 FROM tb_register WHERE username = ? LIMIT 1");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
    echo json_encode(['success'=>false, 'message'=>'該帳號已被註冊']);
    $stmt->close();
    $mysqli->close();
    exit;
}
$stmt->close();

// 密碼雜湊 (生產環境必須)
$passwordHash = password_hash($password, PASSWORD_DEFAULT);

// 寫入資料
$addTime = date('Y-m-d H:i:s');
$stmt = $mysqli->prepare("INSERT INTO tb_register (username, age, password, address, email, add_time) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->bind_param('sissss', $username, $age, $passwordHash, $address, $email, $addTime);

$success = $stmt->execute();
$stmt->close();
$mysqli->close();

echo json_encode([
    'success' => $success,
    'message' => $success ? '註冊成功!' : '註冊失敗,請稍後再試'
]);
?>

資料表結構 (MySQL)

CREATE TABLE `tb_register` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `username` VARCHAR(50) NOT NULL UNIQUE,
  `age` TINYINT UNSIGNED NOT NULL,
  `password` VARCHAR(255) NOT NULL,  -- 存雜湊
  `address` VARCHAR(255) NOT NULL,
  `email` VARCHAR(100) NOT NULL,
  `add_time` DATETIME NOT NULL,
  INDEX `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

安全性強化清單

防護層面 措施 本範例狀態
SQL 注入 預處理語句 ✅ 已實作
XSS 輸出時 `htmlspecialchars` / JSON 編碼 ✅ JSON 自動編碼
CSRF 同源驗證 / CSRF Token ⚠️ 範例未含,生產必加
密碼儲存 bcrypt/argon2 雜湊 ✅ `password_hash`
傳輸加密 HTTPS ⚠️ 部署層面配置
頻率限制 CAPTCHA / IP 限流 ⚠️ 建議加入

除錯技巧

  • 瀏覽器 DevTools → Network → 查看 `_process.php` Request/Response Payload。
  • PHP 錯誤日誌:`tail -f /var/log/php-fpm/error.log`。
  • MySQL 慢查詢日誌分析長耗時 SQL。
copyright © 萬盛學電腦網 all rights reserved