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

如何通过PHP+MySQL+Ajax实现单ID每日点赞更新次数上限控制

单条目每日点赞上限实现方案

这个需求完全可以基于你现有技术栈实现,不需要额外引入其他服务,核心是把单条目日维度的投票计数存在服务端,在投票逻辑里加一层原子校验即可,具体实现步骤如下:

1. 新增日投票计数表

你现有的表只存了条目的总点赞数,需要新增一张专门存每日投票计数的表,用来记录每个投票条目每天累计获得的票数,建表SQL如下:

CREATE TABLE `vote_daily_limit` (
  `item_id` int UNSIGNED NOT NULL COMMENT '对应投票条目的ID',
  `vote_date` date NOT NULL COMMENT '计数归属日期(不带时分秒)',
  `daily_vote_count` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '当日已累计投票数',
  PRIMARY KEY (`item_id`,`vote_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

把item_id和vote_date设为联合主键,一是查询效率高,二是可以配合数据库行锁避免并发超量。

2. 改造后端投票接口逻辑

你原来的逻辑是收到Ajax请求后直接给对应条目的点赞数+1,现在要在更新前加日上限校验,注意必须用数据库事务+行锁保证操作原子性,不然高并发下会出现计数超过上限的问题。
核心逻辑流程:

  • 收到前端传来的投票条目ID,以服务器当前日期为准(不要取前端传的日期,容易被篡改),用PHP的date('Y-m-d')获取当日日期字符串。
  • 开启数据库事务,先查询当前条目在当日的计数记录,查询时加FOR UPDATE行锁,避免其他并发请求同时读取到旧的计数值。
  • 如果当日没有对应计数记录,就初始化一条计数为0的记录。
  • 判断当前计数是否已经达到你设置的上限(比如10次),如果已达上限直接回滚事务,给前端返回「今日投票次数已达上限」的错误响应。
  • 如果没到上限,同步执行两个更新操作:一是把当日计数+1,二是把原条目表的总点赞数+1,之后提交事务,返回投票成功的响应。

PHP核心实现代码参考(基于PDO连接):

<?php
// 提前完成数据库连接、获取前端传入的$itemId,设置每日单条目投票上限
$dailyMaxVote = 10;
$today = date('Y-m-d');

try {
    $pdo->beginTransaction();

    // 查询并锁定当日计数记录
    $stmt = $pdo->prepare("SELECT daily_vote_count FROM vote_daily_limit WHERE item_id = ? AND vote_date = ? FOR UPDATE");
    $stmt->execute([$itemId, $today]);
    $record = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$record) {
        // 当日无记录,初始化
        $insertStmt = $pdo->prepare("INSERT INTO vote_daily_limit (item_id, vote_date, daily_vote_count) VALUES (?, ?, 0)");
        $insertStmt->execute([$itemId, $today]);
        $currentCount = 0;
    } else {
        $currentCount = $record['daily_vote_count'];
    }

    // 校验是否达上限
    if ($currentCount >= $dailyMaxVote) {
        $pdo->rollBack();
        echo json_encode([
            'code' => 403,
            'msg' => '该内容今日投票次数已达上限,请次日再试'
        ]);
        exit;
    }

    // 更新计数和总点赞数
    $updateDaily = $pdo->prepare("UPDATE vote_daily_limit SET daily_vote_count = daily_vote_count + 1 WHERE item_id = ? AND vote_date = ?");
    $updateDaily->execute([$itemId, $today]);

    $updateTotal = $pdo->prepare("UPDATE vote_items SET like_count = like_count + 1 WHERE id = ?");
    $updateTotal->execute([$itemId]);

    $pdo->commit();

    // 返回最新点赞数供前端更新
    $newLikeCount = $pdo->query("SELECT like_count FROM vote_items WHERE id = {$itemId}")->fetchColumn();
    echo json_encode([
        'code' => 0,
        'msg' => '投票成功',
        'data' => ['like_count' => $newLikeCount]
    ]);
} catch (Exception $e) {
    $pdo->rollBack();
    echo json_encode([
        'code' => 500,
        'msg' => '系统错误,请稍后重试'
    ]);
}

3. 前端Ajax逻辑适配

原有投票成功的逻辑保留,新增对返回状态码的判断:如果收到code=403的响应,直接弹出后端返回的提示即可,不要更新页面上的点赞数字。

注意事项

  • 不要用Cookie、localStorage这类前端存储做计数限制,用户清缓存、换设备就能轻易绕过,所有计数逻辑必须落在服务端。
  • 不需要单独写定时任务每日重置计数:因为计数是和日期绑定的,跨天后查询时会自动匹配新日期的记录,从0开始计数,没有额外维护成本。
  • 如果后续需要加「单个用户每日只能给同一条目投1票」的规则,只需要在vote_daily_limit表新增user_id字段,把联合主键改成(item_id, user_id, vote_date),逻辑和上述流程完全一致。

内容的提问来源于stack exchange,提问作者Justin van der Kwaak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:18:20