You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel结合Ajax实现点赞系统时likes表重复插入多条记录如何解决

Laravel Ajax点赞重复插入修复方案

核心问题排查

重复插入问题由以下几个错误共同导致:

  • 前端JS代码放在了activity循环渲染逻辑中,每渲染一条内容就会给.likeMain绑定一次点击事件,单次点击会触发多次Ajax请求
  • 前端选择器使用全局$('.id').val()获取ID,多内容场景下永远只会读取第一个点赞按钮的ID
  • 控制器没有做重复点赞校验,且给Ajax请求返回了重定向响应(重定向仅对普通表单提交有效,对Ajax请求无意义,还可能引发异常重发)
  • 没有数据库层面的唯一校验兜底

修复步骤

1. 前端代码修正

将JS代码从activity循环容器中移出,放到页面全局底部(仅加载一次),同时添加请求锁、修正ID选择逻辑:

<!-- 循环渲染的点赞按钮部分保持不变,只移出script代码 -->
<div class="container">
    @if ( auth()->user()->hasLiked($activity))
    <a href="{{ route('reply.unlike', ['id' => $activity->id ]) }}" class="btn btn-danger btn-xs">Unlike</a>
    @else
    <a class="btn btn-success btn-xs likeMain">
        <input type="hidden" class="id" value="{{ $activity->id }}">
        <input type="hidden" class="user-id" value="{{ $activity->user_id }}">
        Like
    </a>
    @endif
</div>

<!-- 以下代码放到页面</body>标签之前,全局仅写一次 -->
<script>
    jQuery(document).ready(function ($) {
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });
        // 请求锁,避免请求过程中重复触发
        let isLiking = false;
        // 用事件委托绑定点击事件,适配动态加载的内容
        $(document).on('click', '.likeMain', function () {
            if (isLiking) return;
            isLiking = true;
            // 读取当前点击按钮内的隐藏域值,避免全局选择错误
            const ActID = $(this).find('.id').val();
            const userss = $(this).find('.user-id').val();
            $.ajax({
                type: 'POST',
                url: '/replylike',
                data: {
                    ActID: ActID,
                    userss: userss
                },
                success: function (data) {
                    console.log(data);
                    // 可在此处添加点赞成功后的按钮状态切换逻辑
                },
                complete: function () {
                    // 请求完成后释放锁
                    isLiking = false;
                }
            });
        });
    });
</script>

2. 控制器代码修正

添加重复点赞校验,给Ajax请求返回JSON响应,使用firstOrCreate避免重复插入:

public function likeReply(Request $request) 
{
    // 匹配到相同用户+相同内容的点赞记录时直接返回,不存在才创建
    $like = Like::firstOrCreate(
        [
            'likeable_id' => $request->ActID,
            'likeable_type' => 'App\Activity',
            'user_id' => Auth::id()
        ]
    );
    if (!$like->wasRecentlyCreated) {
        return response()->json(['status' => 'error', 'msg' => '您已经点赞过该内容']);
    }
    return response()->json(['status' => 'success', 'msg' => '点赞成功']);
}

3. 数据库层面兜底

给likes表添加唯一联合索引,数据库层面禁止重复点赞记录插入:
执行以下SQL即可:

ALTER TABLE `likes` ADD UNIQUE INDEX `unique_user_like` (`user_id`, `likeable_id`, `likeable_type`);

如果使用Laravel迁移,在likes表的迁移文件中添加以下代码后执行迁移:

$table->unique(['user_id', 'likeable_id', 'likeable_type']);

内容的提问来源于stack exchange,提问作者niel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 17:30:02