根据php项目,协防补位成功次数?

wen PHP项目 2

PHP项目中"协防补位成功次数"的实现方案

在游戏类PHP项目中,"协防补位成功次数"通常是一个玩家统计数据,由于你没有提供具体代码,我按常见实现方式给你完整方案。

根据php项目,协防补位成功次数?

数据库设计

玩家统计主表(推荐)

CREATE TABLE `player_stats` (
  `player_id`     INT UNSIGNED NOT NULL COMMENT '玩家ID',
  `assist_defense_success` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '协防补位成功次数',
  `updated_at`    TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`player_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='玩家统计';

明细流水表(用于防刷、追溯、每日/赛季统计)

CREATE TABLE `assist_defense_log` (
  `id`          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `player_id`   INT UNSIGNED NOT NULL COMMENT '助攻玩家',
  `target_id`   INT UNSIGNED NOT NULL COMMENT '被协防玩家',
  `battle_id`   BIGINT UNSIGNED NOT NULL COMMENT '战斗ID',
  `result`      TINYINT NOT NULL COMMENT '1成功 0失败',
  `created_at`  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_battle_player` (`battle_id`,`player_id`) COMMENT '同一场战斗去重',
  KEY `idx_player_time` (`player_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

uk_battle_player 唯一索引是关键,防止同一场战斗重复 +1(常见刷分漏洞)。

核心服务类

<?php
class AssistDefenseService
{
    private PDO $db;
    public function __construct(PDO $db)
    {
        $this->db = $db;
    }
    /**
     * 记录一次协防补位结果
     * @param int $playerId  协防玩家
     * @param int $targetId  被协防玩家
     * @param int $battleId  战斗ID
     * @param bool $success  是否成功
     * @return bool 是否计为一次有效成功
     */
    public function record(int $playerId, int $targetId, int $battleId, bool $success): bool
    {
        if ($playerId === $targetId) {
            return false; // 不能给自己协防
        }
        $this->db->beginTransaction();
        try {
            // 1. 写流水(唯一索引防重)
            $stmt = $this->db->prepare(
                "INSERT INTO assist_defense_log (player_id, target_id, battle_id, result)
                 VALUES (:p, :t, :b, :r)"
            );
            $stmt->execute([
                ':p' => $playerId,
                ':t' => $targetId,
                ':b' => $battleId,
                ':r' => $success ? 1 : 0,
            ]);
            // 2. 仅成功时累加统计
            if ($success) {
                $upd = $this->db->prepare(
                    "INSERT INTO player_stats (player_id, assist_defense_success)
                     VALUES (:p, 1)
                     ON DUPLICATE KEY UPDATE assist_defense_success = assist_defense_success + 1"
                );
                $upd->execute([':p' => $playerId]);
            }
            $this->db->commit();
            return $success;
        } catch (PDOException $e) {
            $this->db->rollBack();
            // 1062 = 唯一键冲突,说明这场战斗已记录过,直接忽略
            if ($e->errorInfo[1] === 1062) {
                return false;
            }
            throw $e;
        }
    }
    /** 查询玩家协防补位成功次数 */
    public function getCount(int $playerId): int
    {
        $stmt = $this->db->prepare(
            "SELECT assist_defense_success FROM player_stats WHERE player_id = :p"
        );
        $stmt->execute([':p' => $playerId]);
        return (int)($stmt->fetchColumn() ?: 0);
    }
}

调用示例

$service = new AssistDefenseService($pdo);
// 战斗结算时调用
$service->record(
    playerId: 1001,
    targetId: 1002,
    battleId: 20240520001,
    success:  true
);
// 展示用
echo "协防补位成功次数:" . $service->getCount(1001);

进阶:排行榜 / 每日任务

排行榜(Redis + DB 双写)

// 成功后同步到 Redis ZSET,实时排行
$redis->zIncrBy('rank:assist_defense:day:' . date('Ymd'), 1, $playerId);

每日统计(按需取舍)

SELECT COUNT(*) FROM assist_defense_log
WHERE player_id = ? AND result = 1 AND created_at >= ?

或新增 daily_stats(player_id, date, count) 表,避免大表 count。

常见坑点提醒

坑 建议
同一场战斗重复上报 用 UNIQUE(battle_id, player_id) 兜底
并发加一丢失 用 UPDATE ... SET x = x + 1 或 Redis 原子累加
自己给自己协防刷分 校验 player_id != target_id
统计与流水不一致 统计字段以流水为准,定期对账修复
大表 count 慢 用统计表 + Redis,避免频繁 count

如果你能贴出你项目里现有的相关代码(比如战斗结算逻辑、统计表结构),我可以直接帮你定位"协防补位成功次数"该怎么改或在哪查看。

抱歉,评论功能暂时关闭!