本文目录导读:

在PHP项目中统计“快发任意球”(快速发球)的尝试次数,核心是识别什么算一次“快发任意球尝试”,然后设计数据结构和统计逻辑。
由于你没有给出具体的项目背景(是足球游戏?赛事数据平台?还是直播弹幕统计?),我按最常见的情况给你几种方案。
先定义业务规则
足球里“快发任意球”通常指:
- 裁判吹罚任意球后
- 进攻方在防守方未组织好人墙/未退足距离前
- 快速将球发出
所以一次“尝试”可以定义为:
- 球员触球并发球 + 时间间隔 < N秒(比如裁判鸣哨后5秒内)
- 且防守方未准备好
数据库设计
假设你有一张事件表 match_events:
CREATE TABLE match_events (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT NOT NULL,
team_id INT NOT NULL,
player_id INT NOT NULL,
event_type VARCHAR(32), -- 'foul', 'free_kick', 'quick_free_kick_attempt'
event_time DATETIME,
whistle_time DATETIME, -- 裁判鸣哨时间
created_at DATETIME
);
统计某队/某场比赛的快发尝试次数
<?php
// 统计某场比赛某队的快发任意球尝试次数
function countQuickFreeKickAttempts(PDO $pdo, int $matchId, int $teamId): int
{
$sql = "SELECT COUNT(*) FROM match_events
WHERE match_id = :match_id
AND team_id = :team_id
AND event_type = 'quick_free_kick_attempt'";
$stmt = $pdo->prepare($sql);
$stmt->execute([':match_id' => $matchId, ':team_id' => $teamId]);
return (int) $stmt->fetchColumn();
}
如果数据库没有现成标记,需要动态判定
比如你只记录了 foul(犯规)和 pass(传球),需要判断传球是否发生在鸣哨后 5 秒内:
<?php
function detectQuickFreeKicks(PDO $pdo, int $matchId, int $thresholdSeconds = 5): array
{
// 取出所有犯规(任意球)事件
$fouls = $pdo->prepare("
SELECT id, team_id, event_time
FROM match_events
WHERE match_id = ? AND event_type = 'foul'
ORDER BY event_time
");
$fouls->execute([$matchId]);
$fouls = $fouls->fetchAll(PDO::FETCH_ASSOC);
$results = [];
foreach ($fouls as $foul) {
// 找犯规后同一队第一次传球
$stmt = $pdo->prepare("
SELECT id, event_time
FROM match_events
WHERE match_id = ?
AND team_id = ?
AND event_type = 'pass'
AND event_time > ?
ORDER BY event_time ASC
LIMIT 1
");
$stmt->execute([$matchId, $foul['team_id'], $foul['event_time']]);
$pass = $stmt->fetch(PDO::FETCH_ASSOC);
if ($pass) {
$diff = strtotime($pass['event_time']) - strtotime($foul['event_time']);
if ($diff <= $thresholdSeconds) {
$results[] = [
'foul_id' => $foul['id'],
'pass_id' => $pass['id'],
'seconds' => $diff,
];
}
}
}
return $results;
}
聚合统计(按球队/赛季)
<?php
function statsByTeam(PDO $pdo, int $seasonId): array
{
$sql = "SELECT t.name, COUNT(*) AS attempts
FROM match_events e
JOIN teams t ON t.id = e.team_id
JOIN matches m ON m.id = e.match_id
WHERE e.event_type = 'quick_free_kick_attempt'
AND m.season_id = :season
GROUP BY e.team_id
ORDER BY attempts DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([':season' => $seasonId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
性能建议
- 加索引:
(match_id, team_id, event_type, event_time) - 预计算:比赛结束后异步任务把“快发尝试”写入
match_stats表,避免实时 join - 缓存:Redis 缓存每场统计结果,TTL 到比赛结束
- 阈值可配:5秒这个阈值放到配置/数据库,不同联赛规则不同
需要你补充的信息
如果你能告诉我:
- 数据来源是什么(手动录入 / 第三方API / 视频AI识别)?
- 现有表结构?
- “尝试”的判定标准(时间阈值?防守方距离?)
我可以给你更贴合项目的代码和 SQL。
你现在是哪种场景?