PHP注册表单校验错误时跳转而非显示提示的问题如何解决?
问题原因
- 后端所有校验失败的分支都是直接
exit输出HTML格式的错误内容,没有按照AJAX请求要求的application/json格式返回响应 - 前端接收到非JSON格式的响应后,执行
await res.json()会抛出JS异常,代码中断执行,导致表单默认提交行为触发,直接跳转至register.php显示空白错误页 - 你的JSON响应逻辑只写在了注册成功且不需要激活的分支里,错误场景和需要激活的场景都没有处理JSON响应
修复方案
第一步:修改PHP后端代码
所有校验场景统一先收集错误到$errors数组,所有逻辑执行完成后统一处理响应格式:
include 'main.php'; $errors = []; // 统一校验逻辑,全部收集错误到$errors if (!isset($_POST['username'], $_POST['password'], $_POST['cpassword'], $_POST['email'])) { $errors[] = '请完成注册表单所有必填项'; } if (empty($_POST['username']) || empty($_POST['password']) || empty($_POST['email'])) { $errors[] = '请完成注册表单所有必填项'; } if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { $errors[] = '邮箱格式不正确'; } if (!preg_match('/^[a-zA-Z0-9]+$/', $_POST['username'])) { $errors[] = '用户名仅允许使用字母和数字'; } if (strlen($_POST['password']) > 20 || strlen($_POST['password']) < 6) { $errors[] = '密码长度需在6-20位之间'; } if ($_POST['cpassword'] != $_POST['password']) { $errors[] = '两次输入的密码不一致'; } // 没有基础校验错误再查数据库 if (empty($errors)) { $stmt = $pdo->prepare('SELECT id, password FROM accounts WHERE username = ? OR email = ?'); $stmt->execute([ $_POST['username'], $_POST['email'] ]); $account = $stmt->fetch(PDO::FETCH_ASSOC); if ($account) { $errors[] = '用户名或邮箱已被注册'; } else { // 插入账户逻辑 $stmt = $pdo->prepare('INSERT INTO accounts (username, password, email, activation_code) VALUES (?, ?, ?, ?)'); $password = password_hash($_POST['password'], PASSWORD_DEFAULT); $uniqid = account_activation ? uniqid() : 'activated'; $stmt->execute([ $_POST['username'], $password, $_POST['email'], $uniqid ]); session_regenerate_id(); $_SESSION['loggedin'] = TRUE; $_SESSION['name'] = $_POST['username']; $_SESSION['id'] = $pdo->lastInsertId(); $_SESSION['role'] = 'the default role'; if (account_activation) { send_activation_email($_POST['email'], $uniqid); $success_msg = '请查收邮箱完成账户激活'; } else { $success_redirect = 'home.php'; } } } // 统一处理响应,判断是否为AJAX请求 if ($_SERVER['HTTP_ACCEPT'] === "application/json") { if (!empty($errors)) { header("Content-type: application/problem+json"); http_response_code(400); exit(json_encode([ "message" => implode(';', $errors), "errors" => $errors ])); } header("Content-type: application/json"); $response = []; if (isset($success_msg)) { $response['message'] = $success_msg; } if (isset($success_redirect)) { $response['location'] = $success_redirect; } exit(json_encode($response)); } // 非AJAX请求的普通响应(兼容无JS场景) foreach ($errors as $error) : ?> <div class="error"><?= $error ?></div> <?php endforeach; if (isset($success_msg)) { echo '<div class="success">'.$success_msg.'</div>'; } ?>
第二步:优化前端AJAX代码,添加异常捕获
避免JSON解析失败导致代码中断:
document.querySelector(".register form").addEventListener("submit", async (e) => { e.preventDefault() const msgBox = document.querySelector('.msg') msgBox.textContent = '' const form = e.target const body = new FormData(form) try { const res = await fetch(form.action, { method: "POST", headers: { accept: "application/json", }, body }) const data = await res.json() if (res.ok) { if (data.location) { location.href = data.location } if (data.message) { msgBox.textContent = data.message msgBox.classList.remove('error') msgBox.classList.add('success') } } else if (res.status === 400) { msgBox.textContent = data.message msgBox.classList.add('error') msgBox.classList.remove('success') } } catch (e) { msgBox.textContent = '请求失败,请稍后重试' msgBox.classList.add('error') msgBox.classList.remove('success') } })
内容的提问来源于stack exchange,提问作者contributor01010
相关产品推荐
相关产品推荐

