PHP+JS项目:表单提交先入库再更新Cookie索引的问题求助
问题
我有一个基于PHP、HTML、CSS、JavaScript的网页,通过PHP操作数据库插入数据、设置Cookie,JavaScript负责读取Cookie。Cookie中存储了三个内容:
- 科目数组
- 初始值为0的
index变量 - 值为9的
arraySize变量
流程需求
- 页面首次加载时,获取第一个科目
- 用户填写对应科目的表单后,通过POST提交
- 提交后先将当前科目的表单数据插入数据库,再递增
index变量,展示数组中的下一个科目
实际问题
用户为科目'a'填写表单并提交时,数据库中插入的科目却是'b',表单其他数据都正确。
相关代码
code1(提交后递增科目索引的JavaScript代码)
<script> function incrementCookie() { var i = document.cookie.indexOf('index'); let currentIndexValue = document.cookie[i + 6] - '0'; document.cookie='index='+(++currentIndexValue); } incrementCookie(); </script>
code2(插入表单变量到数据库的PHP代码)
if (isset($_POST['insert'])) { $co1 = $_POST['co1']; $co2 = $_POST['co2']; $co3 = $_POST['co3']; $co4 = $_POST['co4']; $co5 = $_POST['co5']; if($GLOBALS['cols'] == 6) $co6 = $_POST['co6']; else $co6 = 0; echo "aayush"; $sb1 = $_POST['sb1']; $sb2 = $_POST['sb2']; $sb3 = $_POST['sb3']; $sb4 = $_POST['sb4']; $sb5 = $_POST['sb5']; $id1 = $_SESSION['id']; $sub = $_POST['subject']; $uname = mysqli_query($con,"select email from users where id = $id1"); $result1 = mysqli_fetch_assoc($uname); $usersemail = $result1['email']; $sql1 = "select email from faculty where subjectalloted = '$sub1' and section = (select section from users where id= '$id1')"; $result2= mysqli_query($con , $sql1); $row1 = mysqli_fetch_assoc($result2); $facultyemail = $row1['email']; // 原代码中存在一行不完整SQL语句,已忽略 $sql = "INSERT INTO `respone` (`subject`,`usersemail`,`facultyemail`, `co1`, `co2`, `co3`, `co4`, `co5`, `co6`, `sb1`, `sb2`, `sb3`, `sb4`, `sb5`) VALUES ('$sub1', '$usersemail', '$facultyemail','$co1', '$co2', '$co3', '$co4', '$co5', '$co6', '$sb1', '$sb2', '$sb3', '$sb4', '$sb5')"; mysqli_query($con, $sql); }
code3(获取科目的PHP代码)
$data = json_decode($_COOKIE['subjectArrayCookie'], true); $index = $_COOKIE['index']; global $sub; $sub = $data[$index]; $_POST['subject'] = $sub;
尝试过的方法
把code2放在code1之前,期望先入库再更新Cookie索引,但因为JavaScript是客户端执行,页面加载时就会提前递增index,导致入库的是下一个科目。
解决方案
核心问题分析
问题根源是客户端JS和服务端PHP执行顺序颠倒:页面加载时JS立刻执行incrementCookie(),先把index递增,之后PHP才读取这个已更新的index获取科目,最终导致入库的是下一个科目。
正确实现方案
1. 由PHP全权处理Cookie递增(推荐)
既然入库是服务端操作,Cookie更新也应该放在PHP中,彻底避免客户端提前修改:
- POST提交后,PHP先读取当前未递增的
index,用它获取当前科目并完成数据库插入 - 插入成功后,再递增
index并更新Cookie
修改后代码示例:
// 先读取当前未递增的index if (isset($_COOKIE['subjectArrayCookie']) && isset($_COOKIE['index'])) { $data = json_decode($_COOKIE['subjectArrayCookie'], true); $currentIndex = (int)$_COOKIE['index']; $sub = $data[$currentIndex]; } // 执行数据库插入 if (isset($_POST['insert'])) { // 省略其他表单变量获取代码 $usersemail = $result1['email']; // 替换原代码中的$sub1为当前科目$sub $sql1 = "select email from faculty where subjectalloted = '$sub' and section = (select section from users where id= '$id1')"; // 省略其他代码 $sql = "INSERT INTO `respone` (`subject`,`usersemail`,`facultyemail`, ...) VALUES ('$sub', '$usersemail', '$facultyemail', ...)"; $insertResult = mysqli_query($con, $sql); // 插入成功后才更新Cookie if ($insertResult) { $newIndex = $currentIndex + 1; // 设置Cookie时指定路径,避免作用域问题 setcookie('index', $newIndex, time() + 3600, '/'); } }
2. 调整JS执行时机(可选)
如果坚持用JS处理Cookie,必须禁止页面加载时自动执行incrementCookie(),改为在确认入库成功后再执行:
- 改用AJAX提交表单,在成功回调中调用
incrementCookie() - 或让PHP在入库成功后输出执行JS的代码
AJAX方式示例:
<form id="subjectForm" method="POST"> <!-- 表单内容 --> <button type="submit">提交</button> </form> <script> document.getElementById('subjectForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); fetch('', { method: 'POST', body: formData }).then(response => response.text()) .then(data => { // 假设PHP入库成功返回标识文本 if (data.includes('aayush')) { incrementCookie(); window.location.reload(); } }); }); // 优化Cookie读取逻辑,避免index后有其他Cookie的情况 function incrementCookie() { const cookies = document.cookie.split(';').reduce((acc, cookie) => { const [key, value] = cookie.trim().split('='); acc[key] = value; return acc; }, {}); let currentIndexValue = parseInt(cookies['index'] || 0); document.cookie = `index=${++currentIndexValue}; path=/; max-age=3600`; } </script>
3. 修复其他潜在问题
- 原code2中
$sub1未定义,需替换为当前科目变量$sub - 存在SQL注入风险,必须使用预处理语句:
$stmt = $con->prepare("INSERT INTO `respone` (`subject`,`usersemail`,`facultyemail`, `co1`, `co2`, `co3`, `co4`, `co5`, `co6`, `sb1`, `sb2`, `sb3`, `sb4`, `sb5`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->bind_param("ssssssssssssss", $sub, $usersemail, $facultyemail, $co1, $co2, $co3, $co4, $co5, $co6, $sb1, $sb2, $sb3, $sb4, $sb5); $stmt->execute();
内容的提问来源于stack exchange,提问作者Sarraayush
相关产品推荐
相关产品推荐

