PHP项目中客队客场表现评估方法
在PHP体育数据项目中,评估客队客场表现通常需要从多个维度建模,以下是完整的评估思路和代码示例。

核心评估维度
| 维度 | 说明 | 权重建议 |
|---|---|---|
| 客场胜率 | 客场获胜场次 / 客场总场次 | 25% |
| 客场进球能力 | 场均进球数 | 20% |
| 客场防守能力 | 场均失球数 | 20% |
| 近期客场状态 | 最近5-6场客场表现 | 20% |
| 对手强度修正 | 根据对手排名加权 | 15% |
数据库设计
CREATE TABLE matches (
id INT PRIMARY KEY AUTO_INCREMENT,
home_team_id INT,
away_team_id INT,
home_goals INT,
away_goals INT,
match_date DATE,
league_id INT,
status TINYINT DEFAULT 1 -- 1已结束
);
CREATE TABLE teams (
id INT PRIMARY KEY,
name VARCHAR(50),
league_id INT
);
核心评估类(PHP实现)
<?php
class AwayPerformanceEvaluator
{
private PDO $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
/**
* 综合评估客队客场表现
* @param int $teamId 客队ID
* @param int $recentN 近期场次
* @return array
*/
public function evaluate(int $teamId, int $recentN = 10): array
{
$stats = $this->getAwayStats($teamId, $recentN);
if ($stats['total'] == 0) {
return ['score' => 50, 'detail' => $stats, 'msg' => '无客场数据'];
}
// 1. 客场胜率得分(0-100)
$winRateScore = ($stats['wins'] / $stats['total']) * 100;
// 2. 进球能力得分(以场均1.5球为满分基准)
$attackScore = min(100, ($stats['goals_for'] / $stats['total']) / 1.5 * 100);
// 3. 防守能力得分(以场均失1.5球为0分基准)
$defenseScore = max(0, 100 - ($stats['goals_against'] / $stats['total']) / 1.5 * 100);
// 4. 近期状态(加权,越近权重越高)
$recentScore = $this->getRecentFormScore($teamId, 5);
// 5. 对手强度修正
$opponentFactor = $this->getOpponentStrengthFactor($teamId, $recentN);
// 综合加权
$totalScore = (
$winRateScore * 0.25 +
$attackScore * 0.20 +
$defenseScore * 0.20 +
$recentScore * 0.20 +
$opponentFactor * 0.15
);
return [
'score' => round($totalScore, 2),
'detail' => [
'win_rate_score' => round($winRateScore, 2),
'attack_score' => round($attackScore, 2),
'defense_score' => round($defenseScore, 2),
'recent_form' => round($recentScore, 2),
'opponent_factor' => round($opponentFactor, 2),
'raw_stats' => $stats,
],
];
}
/**
* 获取客队客场数据统计
*/
private function getAwayStats(int $teamId, int $limit): array
{
$sql = "SELECT
COUNT(*) AS total,
SUM(CASE WHEN away_goals > home_goals THEN 1 ELSE 0 END) AS wins,
SUM(CASE WHEN away_goals = home_goals THEN 1 ELSE 0 END) AS draws,
SUM(CASE WHEN away_goals < home_goals THEN 1 ELSE 0 END) AS losses,
SUM(away_goals) AS goals_for,
SUM(home_goals) AS goals_against
FROM matches
WHERE away_team_id = :tid AND status = 1
ORDER BY match_date DESC
LIMIT :lim";
// 注意:MySQL LIMIT 绑定需要 bindValue 指定 INT 类型
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(':tid', $teamId, PDO::PARAM_INT);
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* 近期状态得分:加权最近比赛
*/
private function getRecentFormScore(int $teamId, int $n): float
{
$sql = "SELECT away_goals, home_goals, match_date
FROM matches
WHERE away_team_id = :tid AND status = 1
ORDER BY match_date DESC
LIMIT :lim";
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(':tid', $teamId, PDO::PARAM_INT);
$stmt->bindValue(':lim', $n, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($rows)) return 50;
$weighted = 0;
$totalWeight = 0;
foreach ($rows as $i => $m) {
// 越近的比赛权重越高:权重 = n - i
$weight = $n - $i;
$points = 1; // 默认胜
if ($m['away_goals'] == $m['home_goals']) $points = 0.5;
if ($m['away_goals'] < $m['home_goals']) $points = 0;
$weighted += $points * $weight;
$totalWeight += $weight;
}
// 0~1 转 0~100
return ($weighted / $totalWeight) * 100;
}
/**
* 对手强度系数:对手越强,同样表现得分越高
* 使用对手主场的平均胜率作为强度指标
*/
private function getOpponentStrengthFactor(int $teamId, int $limit): float
{
$sql = "SELECT m.home_team_id,
AVG(CASE WHEN m2.home_goals > m2.away_goals THEN 1 ELSE 0 END) AS home_win_rate
FROM matches m
JOIN matches m2 ON m2.home_team_id = m.home_team_id AND m2.status = 1
WHERE m.away_team_id = :tid AND m.status = 1
GROUP BY m.home_team_id
ORDER BY m.match_date DESC
LIMIT :lim";
// 简化实现:返回平均对手主场胜率换算的系数
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(':tid', $teamId, PDO::PARAM_INT);
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($rows)) return 50;
$avg = array_sum(array_column($rows, 'home_win_rate')) / count($rows);
// 对手越强(胜率高),系数越高,将0.2~1.0映射到30~100
return min(100, 30 + $avg * 70);
}
}
使用示例
$pdo = new PDO('mysql:host=localhost;dbname=football', 'root', '');
$evaluator = new AwayPerformanceEvaluator($pdo);
$result = $evaluator->evaluate($awayTeamId = 12, $recentN = 10);
print_r($result);
/*
[
'score' => 68.45,
'detail' => [
'win_rate_score' => 60,
'attack_score' => 80,
'defense_score' => 66.7,
'recent_form' => 70,
'opponent_factor' => 65,
'raw_stats' => [...]
]
]
*/
进阶优化建议
-
引入 xG / xGA(预期进球)
比单纯进球数更能反映真实实力,减少运气因素。 -
对手强度用 ELO 评分
比主场胜率更科学,可动态更新:$expected = 1 / (1 + pow(10, ($opponentElo - $teamElo) / 400));
-
分联赛 / 分主客场独立计算
不同联赛客队优势差异大,应分开建模。 -
考虑赛程密度与休息天数
DATEDIFF(match_date, LAG(match_date) OVER (ORDER BY match_date)) AS rest_days
-
缓存结果
评估计算较重,可用 Redis 缓存:$key = "away_eval:{$teamId}:{$recentN}"; if ($cached = $redis->get($key)) return json_decode($cached, true); -
异常值处理
剔除大比分垃圾时间(如 0-7)或使用中位数代替平均数。
输出评分等级参考
| 得分区间 | 客场表现等级 | 含义 |
|---|---|---|
| 80-100 | A+ 极强 | 客场抢分能力强 |
| 65-79 | A 强 | 客场稳定 |
| 50-64 | B 中等 | 主客场差异不大 |
| 35-49 | C 弱 | 客场乏力 |
| 0-34 | D 极弱 | 客场送分童子 |
客队客场表现评估的核心是——用历史客场数据 + 近期权重 + 对手强度修正做加权综合,PHP 项目中建议封装成独立的 Evaluator 类,便于在不同场景(赛前预测、报表、赔率分析)中复用。