修复PHP MySQL jQuery Ajax实现Feed流点赞时全帖点赞数同步错误问题
类Facebook新闻Feed点赞计数异常修复方案
问题根因
- 前端Ajax成功回调使用全局选择器
$(".ajax_like_result"),会匹配页面内所有带该class的点赞数展示节点,导致单次点赞操作会覆盖所有帖子的计数 - 直接将class替换为id的方案不符合HTML id全局唯一的规范,且未在点击事件中关联当前点击按钮对应的计数节点,因此仅第一条帖子功能正常,其余帖子无响应
- 后端代码存在3个明显问题:直接拼接前端参数到SQL语句存在SQL注入风险、先查询再更新的逻辑在高并发下会出现计数偏差、声明返回json格式但实际直接输出数字会触发前端解析报错,还遗留了无意义的
enter code here冗余字符
分步修复代码
1. 前端交互逻辑修复
点击事件触发时先缓存当前点击的按钮节点,回调时仅操作该节点内部的点赞数展示元素,不做全局匹配;同时修正返回数据类型避免解析错误。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ $('.ajax_like').on('click', function () { // 缓存当前点击的帖子点赞按钮节点,后续操作仅针对当前帖子 const currentPostItem = $(this); var post_id = currentPostItem.val(); var page = currentPostItem.attr("data-id"); $.ajax({ type: 'POST', url: 'like.php', data: {post_id:post_id, page:page}, dataType: 'text', // 后端直接返回数字,使用text类型避免json解析报错 success: function(data){ // 仅更新当前帖子下的点赞计数节点,不影响其他帖子 currentPostItem.find(".ajax_like_result").html(data); } }); }); }); </script>
2. HTML模板调整
不需要把class属性替换为id,保持原有class写法即可,因为已经通过节点父子关系锁定了当前帖子的计数元素,原有模板代码可正常使用:
<li class="ajax_like" type="submit" name="data-id" data-id="<?php echo $page;?>" value="<? echo $post_id;?>"> <div class="ajax_like_result"><?php print $likes;?></div> </li>
3. 后端接口like.php修复
- 使用预处理语句绑定参数,新增表名白名单校验,封堵SQL注入漏洞
- 去掉先查再改的冗余逻辑,直接用SQL内置的自增语法更新计数,避免并发下计数不准
- 增加基础参数校验、登录态校验,删除冗余遗留代码
<?php session_start(); $conn=mysqli_connect("localhost", "u1068033_ab24", "ab@24", "u1068033_ab24"); mysqli_set_charset($conn,"utf8"); // 未登录状态直接终止请求 if(empty($_SESSION['id'])){ exit("0"); } $id = $_SESSION['id']; // 参数格式校验 $get_post_id = intval($_POST['post_id']); // 配置允许访问的表名白名单,替换为你业务中实际用到的表名即可,禁止直接拼接前端传入的表名 $allowed_pages = ['posts', 'user_wall_posts']; $page = $_POST['page']; if(!in_array($page, $allowed_pages) || $get_post_id <= 0){ exit("参数非法"); } // 直接执行自增操作,不需要提前查询当前点赞数,避免并发计数偏差 $update_stmt = mysqli_prepare($conn, "UPDATE `$page` SET `likes` = `likes` + 1 WHERE `post_id` = ?"); mysqli_stmt_bind_param($update_stmt, "i", $get_post_id); mysqli_stmt_execute($update_stmt); // 查询更新后的点赞数返回前端 $query_stmt = mysqli_prepare($conn, "SELECT `likes` FROM `$page` WHERE `post_id` = ?"); mysqli_stmt_bind_param($query_stmt, "i", $get_post_id); mysqli_stmt_execute($query_stmt); $result = mysqli_stmt_get_result($query_stmt); $row = mysqli_fetch_assoc($result); echo $row['likes']; ?>
可选优化项
- 增加点赞防抖逻辑,避免用户快速连续点击按钮触发重复请求
- 新增用户点赞关联表,校验用户是否已对当前帖子点赞,防止同一用户重复刷赞
- 取消前端传表名的逻辑,通过帖子类型枚举在后端做映射,进一步降低安全风险
内容的提问来源于stack exchange,提问作者mhbd2009
相关产品推荐
相关产品推荐

