本文目录导读:

在PHP项目中统计“门将谁更忙”,核心逻辑并不在于PHP本身,而在于你的数据模型(数据库字段)和统计口径,PHP只是负责把数据库里的数字取出来算一下。
下面我从业务定义、数据库设计、PHP统计代码三个层面给你一个完整的方案。
第一步:定义“忙”的标准(关键)
“忙”不能只看“扑救次数”,否则后卫解围多也忙,通常我们用 “被射正次数” 或 “实际扑救次数” 来衡量。
建议你统计以下三个指标,用组合来判断:
- 扑救次数(Saves):真正把球扑出去的次数。
- 被射正次数(Shots on Target Against):对方射正门框范围内的次数(这代表门将面临了威胁)。
- 触球次数(Touches):门将参与组织传球的次数(如果是传控球队的门将,这个数据会很高)。
“更忙”的推荐算法(加权公式): [ 忙碌度 = (扑救次数 \times 1.0) + (被射正次数 \times 0.5) + (出击/解围次数 \times 0.8) ] 或者简单点,直接 比较“扑救次数” ,因为这是最直观的。
第二步:数据库表设计(示例)
假设你有两张表:players(球员表)和 match_stats(比赛统计表)。
-- 球员表
CREATE TABLE players (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
position VARCHAR(10) DEFAULT 'GK' -- 门将
);
-- 比赛统计表(每场比赛每个门将一行)
CREATE TABLE match_stats (
id INT PRIMARY KEY AUTO_INCREMENT,
player_id INT NOT NULL,
match_id INT NOT NULL,
saves INT DEFAULT 0, -- 扑救次数
shots_on_target_against INT DEFAULT 0, -- 被射正次数
clearances INT DEFAULT 0, -- 出击解围次数
touches INT DEFAULT 0, -- 触球次数
FOREIGN KEY (player_id) REFERENCES players(id)
);
第三步:PHP 统计代码(万金油写法)
假设你使用 PDO 连接MySQL,下面代码会输出“谁最忙”的排行榜。
<?php
// 1. 连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=football', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 2. 接收前端传来的筛选条件(例如赛季年份)
$season = $_GET['season'] ?? '2024';
// 3. 核心SQL:统计每个门将的总工作量
$sql = "
SELECT
p.id,
p.name,
COUNT(ms.match_id) AS matches_played,
SUM(ms.saves) AS total_saves,
SUM(ms.shots_on_target_against) AS total_sota,
SUM(ms.clearances) AS total_clearances,
-- 计算忙碌度(这里把扑救权重设为1,被射正权重0.6,解围权重0.8)
(SUM(ms.saves) * 1.0 + SUM(ms.shots_on_target_against) * 0.6 + SUM(ms.clearances) * 0.8) AS busy_score,
-- 计算场均扑救(有时候总次数多是因为出场多,场均更能说明问题)
ROUND(SUM(ms.saves) / COUNT(ms.match_id), 2) AS avg_saves_per_match
FROM players p
INNER JOIN match_stats ms ON p.id = ms.player_id
INNER JOIN matches m ON ms.match_id = m.id -- 假设有比赛表,包含 season 字段
WHERE p.position = 'GK'
AND m.season = :season
GROUP BY p.id, p.name
ORDER BY busy_score DESC -- 按忙碌度排序,最忙的排最前
";
$stmt = $pdo->prepare($sql);
$stmt->execute(['season' => $season]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 4. 输出结果表
header('Content-Type: text/html; charset=utf-8');
echo "<h2>{$season}赛季 门将忙碌度排行榜</h2>";
echo "<table border='1' cellpadding='8' style='border-collapse:collapse;'>";
echo "<tr>
<th>排名</th>
<th>门将</th>
<th>出场</th>
<th>总扑救</th>
<th>被射正</th>
<th>出击解围</th>
<th>场均扑救</th>
<th>忙碌评分</th>
</tr>";
$rank = 1;
foreach ($results as $row) {
// 高亮第一名
$style = ($rank == 1) ? "background-color: #ffd700; font-weight:bold;" : "";
echo "<tr style='{$style}'>";
echo "<td>{$rank}</td>";
echo "<td>{$row['name']}</td>";
echo "<td>{$row['matches_played']}</td>";
echo "<td>{$row['total_saves']}</td>";
echo "<td>{$row['total_sota']}</td>";
echo "<td>{$row['total_clearances']}</td>";
echo "<td>{$row['avg_saves_per_match']}</td>";
echo "<td><strong>{$row['busy_score']}</strong></td>";
echo "</tr>";
$rank++;
}
echo "</table>";
// 5. 单独结论:谁是“最忙”的?
if (!empty($results)) {
$busiest = $results[0];
echo "<p style='font-size:20px;color:red;'>🏆 <b>{$busiest['name']}</b> 是本赛季最忙的门将,场均扑救 {$busiest['avg_saves_per_match']} 次。</p>";
}
第四步:扩展思考(很关键)
如果直接比较扑救次数,对弱队门将不公平(因为弱队被射门多),你可以加入球队控球率或预期失球数(xGA)来修正。
| 场景 | 判断方法 |
|---|---|
| 单纯看谁扑救动作多 | 直接 SUM(saves) 排序 |
| 看谁承受压力大 | 按 SUM(shots_on_target_against) 排序 |
| 看谁在球队里不可或缺 | 计算 (扑救成功率 = 扑救数 / (扑救数 + 失球数)),成功率高的反而“稳” |
| 看谁“累” | 用上面的 busy_score 加权重算 |
补充:如果不想写SQL,用PHP数组统计
如果你历史数据在数组里,可以用PHP的 array_reduce:
$stats = [
['name' => '阿利松', 'saves' => 45, 'sota' => 60, 'clearances' => 10],
['name' => '埃德森', 'saves' => 30, 'sota' => 40, 'clearances' => 25],
['name' => '拉亚', 'saves' => 50, 'sota' => 55, 'clearances' => 8],
];
usort($stats, function($a, $b) {
$score_a = $a['saves'] + $a['sota']*0.6 + $a['clearances']*0.8;
$score_b = $b['saves'] + $b['sota']*0.6 + $b['clearances']*0.8;
return $score_b <=> $score_a;
});
print_r($stats[0]); // 最忙的门将
在PHP项目里,“统计扑救次数”很简单,最难的是定义“更忙”的算法,建议你在后台管理界面让用户选择统计维度(按次数、按成功率、按权重评分),然后把最终的SQL拼接好执行即可。
如果你把具体的数据库表结构(字段名)发给我,我可以帮你写一条精确的SQL。