数据库view_count字段未更新:AJAX请求异常排查求助
修复职位浏览量自增功能的问题
核心问题与修复步骤
1. 阻止a标签默认跳转,避免中断AJAX请求
点击<a>标签时浏览器会立即执行跳转,导致AJAX请求还未完成就被终止。需要在点击事件中先阻止默认行为,待AJAX请求完成后再手动跳转。
2. 统一前后端数据格式:后端返回JSON响应
前端代码中使用JSON.parse()解析响应,但当前后端返回的是纯文本,会直接抛出语法错误。需要修改后端返回标准JSON格式数据。
3. 批量绑定事件(适配多职位场景)
如果是循环生成多个职位按钮,原脚本中通过ID绑定事件的方式会失效(循环中$row['job_id']会被覆盖),改用类选择器批量绑定事件更可靠。
4. 修复SQL注入风险
直接将用户输入拼入SQL语句存在安全隐患,改用MySQLi预处理语句避免注入。
5. 修正前端错误处理逻辑
原onreadystatechange中的else分支会在请求未完成时(readyState≠4)就打印错误,干扰排查,应仅在请求完成且状态码异常时处理错误。
修正后的完整代码
1. 职位按钮HTML(循环渲染场景)
<a href="explore-job.php?jobid=<?php echo $row['job_id']; ?>" target="_blank" class="btn btn-primary view-job-btn" data-job-id="<?php echo $row['job_id']; ?>"> View This Job <span class="view-count"><?php echo $row['view_count']; ?></span> </a>
2. 前端JavaScript代码
document.addEventListener('DOMContentLoaded', function() { // 批量获取所有职位按钮并绑定事件 const viewJobBtns = document.querySelectorAll('.view-job-btn'); viewJobBtns.forEach(btn => { btn.addEventListener('click', function(e) { // 阻止默认跳转行为 e.preventDefault(); const jobId = this.dataset.jobId; const targetUrl = this.href; const viewCountElement = this.querySelector('.view-count'); const xhr = new XMLHttpRequest(); xhr.open('POST', 'update-view-count.php', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() { if (xhr.status === 200) { try { const response = JSON.parse(xhr.responseText); if (response.success) { // 更新页面显示的浏览量 const currentViewCount = parseInt(viewCountElement.textContent); viewCountElement.textContent = currentViewCount + 1; } else { console.error('更新失败:', response.message); } } catch (err) { console.error('解析响应失败:', err); } } else { console.error('请求失败,状态码:', xhr.status); } // 无论请求成功与否,都跳转到职位详情页 window.open(targetUrl, '_blank'); }; xhr.onerror = function() { console.error('网络请求错误'); window.open(targetUrl, '_blank'); }; xhr.send('jobId=' + encodeURIComponent(jobId)); }); }); });
3. update-view-count.php后端代码
<?php error_reporting(E_ALL); ini_set('display_errors', 1); header('Content-Type: application/json'); // 设置响应为JSON格式 $response = ['success' => false, 'message' => '未知错误']; if(isset($_POST['jobId'])) { $jobId = $_POST['jobId']; $servername = "localhost"; $username = "root"; $password = ""; $dbname = "job_portal"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { $response['message'] = "数据库连接失败: " . $conn->connect_error; echo json_encode($response); exit; } // 使用预处理语句防止SQL注入 $sql = "UPDATE tbl_jobs SET view_count = view_count + 1 WHERE enc_id = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $jobId); // 假设enc_id是字符串类型,根据实际字段类型调整 if ($stmt->execute()) { if ($stmt->affected_rows > 0) { $response['success'] = true; $response['message'] = "浏览量更新成功"; } else { $response['message'] = "未找到对应职位或无需更新"; } } else { $response['message'] = "数据库执行错误: " . $stmt->error; } $stmt->close(); $conn->close(); } else { $response['message'] = "未获取到职位ID"; } echo json_encode($response); ?>
额外优化建议
- 添加防抖逻辑,避免用户短时间内多次点击导致重复请求。
- 考虑使用
fetch API替代XMLHttpRequest,代码更简洁易读。 - 后台保留详细的更新日志,方便后续排查问题。
内容的提问来源于stack exchange,提问作者Md. Jahangir Alam
相关产品推荐
相关产品推荐

