
本文详解如何在不刷新页面的前提下,使用 ajax 从前端 javascript 向后端 php 发送用户姓名与游戏得分,并持久化存储到 mysql 数据库,涵盖跨域防护、sql 注入防范及完整前后端协作流程。
在网页蛇游戏中实现排行榜功能,关键在于将前端产生的用户标识(如昵称)和实时得分,安全、可靠、无感地传递至后端数据库。由于浏览器出于安全限制,JavaScript 无法直接连接 MySQL(缺少驱动且暴露数据库凭证风险),必须通过 HTTP 请求将数据交由服务端脚本(如 PHP)中转处理。推荐采用 AJAX 异步 POST 请求,确保游戏体验不中断,同时兼顾安全性与可维护性。
✅ 前端:使用原生 Fetch API 提交数据(无需 jQuery)
现代项目建议优先使用原生 fetch(),轻量且兼容主流浏览器。将您代码中标注的注释块替换为以下逻辑:
// 在游戏重置前(snake 重置之前)发送数据
const username = document.getElementById("userData").innerHTML.trim();
const score = snake.score;
// 防御性检查:避免空用户名或无效分数
if (username && username !== "____" && Number.isInteger(score) && score >= 0) {
fetch('save_score.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
username: username,
score: score
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('✅ 得分已成功提交至排行榜');
} else {
console.warn('⚠️ 提交失败:', data.message);
}
})
.catch(error => {
console.error('❌ 网络错误或服务器异常:', error);
});
}? 提示:URLSearchParams 自动处理 URL 编码,比手动拼接更安全;trim() 防止空格导致的脏数据。
✅ 后端:PHP 脚本(save_score.php)—— 安全接收并写入 MySQL
创建 save_score.php 文件,务必启用 PDO 预处理语句防止 SQL 注入,并添加基础校验:
PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
// 验证并过滤输入
$user = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$score = filter_input(INPUT_POST, 'score', FILTER_VALIDATE_INT);
if (!$user || strlen($user) > 50 || $score === false || $score < 0) {
throw new Exception('参数无效:用户名需为1-50字符,得分需为非负整数');
}
// 使用预处理语句插入数据
$stmt = $pdo->prepare("INSERT INTO snake_scores (username, score, created_at) VALUES (?, ?, NOW())");
$stmt->execute([$user, $score]);
echo json_encode(['success' => true, 'message' => '提交成功']);
} catch (Exception $e) {
error_log('SaveScore Error: ' . $e->getMessage());
echo json_encode([
'success' => false,
'message' => '服务器内部错误,请稍后重试'
]);
}
?>⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 绝不暴露数据库密码:生产环境应将配置移至 Web 根目录外的 .env 或专用配置文件;
- 表结构建议(执行一次):
CREATE TABLE IF NOT EXISTS snake_scores ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, score INT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_score (score DESC) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;- CORS 策略:生产环境请将 Access-Control-Allow-Origin 替换为具体域名(如 'https://your-site.com'),禁用通配符 * 配合凭据(cookies)。
✅ 进阶建议:提升健壮性与用户体验
- 防重复提交:可在前端按钮/提交逻辑中添加节流(throttle)或禁用标志,避免玩家快速点击导致多条记录;
- 本地缓存兜底:若网络异常,可用 localStorage 暂存未提交数据,页面重载后尝试重发;
- 排行榜查询分离:另建 get_leaderboard.php 接口,配合 ORDER BY score DESC LIMIT 10 返回 Top10,供首页动态加载;
- 用户会话绑定:结合 PHP Session 或 JWT,关联用户登录态,替代纯前端 prompt 输入,提升可信度。
通过以上结构化实现,你不仅解决了“JS 如何连 MySQL”的核心误区,更构建了一套符合 Web 安全最佳实践的数据上报链路——前端专注交互,后端专注存储与校验,职责清晰,扩展性强。











