本文目录导读:

我来帮你创建一个PHP项目来统计禁区内射门次数对比,这个功能通常用于足球数据分析。
数据库设计
-- 球队表
CREATE TABLE teams (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
short_name VARCHAR(50)
);
-- 比赛表
CREATE TABLE matches (
id INT PRIMARY KEY AUTO_INCREMENT,
home_team_id INT,
away_team_id INT,
match_date DATE,
competition VARCHAR(100),
FOREIGN KEY (home_team_id) REFERENCES teams(id),
FOREIGN KEY (away_team_id) REFERENCES teams(id)
);
-- 射门记录表
CREATE TABLE shots (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT,
team_id INT,
player_id INT,
shot_time INT, -- 比赛时间(分钟)
is_penalty_area BOOLEAN, -- 是否禁区内
is_goal BOOLEAN, -- 是否进球
shot_type VARCHAR(50), -- 射门方式:右脚、左脚、头球等
x_coordinate DECIMAL(4,2), -- x坐标(用于技术分析)
y_coordinate DECIMAL(4,2), -- y坐标
FOREIGN KEY (match_id) REFERENCES matches(id),
FOREIGN KEY (team_id) REFERENCES teams(id)
);
PHP配置和数据库连接
// config.php - 数据库配置文件
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'football_stats');
define('DB_USER', 'root');
define('DB_PASS', 'your_password');
function getConnection() {
try {
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4';
$pdo = new PDO($dsn, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
} catch (PDOException $e) {
die('数据库连接失败: ' . $e->getMessage());
}
}
?>
射门统计类
// ShotStatistics.php - 射门统计类
<?php
class ShotStatistics {
private $db;
public function __construct() {
$this->db = getConnection();
}
// 获取比赛双方禁区内射门统计
public function getPenaltyAreaShotsByMatch($matchId) {
$sql = "SELECT
t.id as team_id,
t.name as team_name,
COUNT(CASE WHEN s.is_penalty_area = 1 THEN 1 END) as area_shots,
COUNT(CASE WHEN s.is_penalty_area = 1 AND s.is_goal = 1 THEN 1 END) as area_goals,
COUNT(CASE WHEN s.is_penalty_area = 0 THEN 1 END) as outside_shots,
COUNT(CASE WHEN s.is_penalty_area = 0 AND s.is_goal = 1 THEN 1 END) as outside_goals,
COUNT(*) as total_shots
FROM matches m
INNER JOIN teams t ON t.id IN (m.home_team_id, m.away_team_id)
LEFT JOIN shots s ON s.match_id = m.id AND s.team_id = t.id
WHERE m.id = ?
GROUP BY t.id, t.name";
$stmt = $this->db->prepare($sql);
$stmt->execute([$matchId]);
return $stmt->fetchAll();
}
// 获取多场比赛的禁区内射门统计
public function getSeasonPenaltyAreaStats($teamId = null, $startDate = null, $endDate = null) {
$params = [];
$sql = "SELECT
t.id as team_id,
t.name as team_name,
COUNT(s.id) as total_shots,
SUM(s.is_penalty_area) as area_shots,
SUM(CASE WHEN s.is_penalty_area = 1 AND s.is_goal = 1 THEN 1 ELSE 0 END) as area_goals,
ROUND(SUM(s.is_penalty_area) / COUNT(s.id) * 100, 2) as area_shot_percentage,
ROUND(SUM(CASE WHEN s.is_penalty_area = 1 AND s.is_goal = 1 THEN 1 ELSE 0 END) /
NULLIF(SUM(s.is_penalty_area), 0) * 100, 2) as area_conversion_rate
FROM teams t
LEFT JOIN shots s ON s.team_id = t.id
LEFT JOIN matches m ON m.id = s.match_id
WHERE 1=1";
if ($teamId) {
$sql .= " AND t.id = ?";
$params[] = $teamId;
}
if ($startDate) {
$sql .= " AND m.match_date >= ?";
$params[] = $startDate;
}
if ($endDate) {
$sql .= " AND m.match_date <= ?";
$params[] = $endDate;
}
$sql .= " GROUP BY t.id, t.name ORDER BY area_shots DESC";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
// 获取球员禁区内射门统计
public function getPlayerAreaShots($playerId) {
$sql = "SELECT
p.name as player_name,
COUNT(*) as total_shots,
SUM(CASE WHEN s.is_penalty_area = 1 THEN 1 ELSE 0 END) as area_shots,
SUM(CASE WHEN s.is_penalty_area = 1 AND s.is_goal = 1 THEN 1 ELSE 0 END) as area_goals
FROM players p
LEFT JOIN shots s ON s.player_id = p.id
WHERE p.id = ?
GROUP BY p.name";
$stmt = $this->db->prepare($sql);
$stmt->execute([$playerId]);
return $stmt->fetch();
}
// 获取每场比赛禁区内射门时间分布
public function getShotTimeDistribution($matchId) {
$sql = "SELECT
CASE
WHEN shot_time BETWEEN 0 AND 15 THEN '0-15分钟'
WHEN shot_time BETWEEN 16 AND 30 THEN '16-30分钟'
WHEN shot_time BETWEEN 31 AND 45 THEN '31-45分钟'
WHEN shot_time BETWEEN 46 AND 60 THEN '46-60分钟'
WHEN shot_time BETWEEN 61 AND 75 THEN '61-75分钟'
ELSE '76-90分钟'
END as time_period,
COUNT(CASE WHEN is_penalty_area = 1 THEN 1 END) as area_shots,
COUNT(CASE WHEN is_penalty_area = 0 THEN 1 END) as outside_shots,
COUNT(*) as total_shots
FROM shots
WHERE match_id = ?
GROUP BY time_period
ORDER BY shot_time";
$stmt = $this->db->prepare($sql);
$stmt->execute([$matchId]);
return $stmt->fetchAll();
}
}
?>
页面展示
// compare_shots.php - 禁区内射门对比页面
<?php
require_once 'config.php';
require_once 'ShotStatistics.php';
$stats = new ShotStatistics();
// 获取比赛列表(用于选择)
$db = getConnection();
$matches = $db->query("SELECT m.id,
home.name as home_team,
away.name as away_team,
m.match_date
FROM matches m
JOIN teams home ON home.id = m.home_team_id
JOIN teams away ON away.id = m.away_team_id
ORDER BY m.match_date DESC LIMIT 10")->fetchAll();
$selectedMatch = isset($_GET['match_id']) ? $_GET['match_id'] : (isset($matches[0]) ? $matches[0]['id'] : null);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">禁区内射门统计对比</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.container { max-width: 1200px; margin-top: 30px; }
.card { margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.stat-card { border-radius: 8px; }
.area-highlight { background-color: #28a745; color: white; }
.progress { height: 30px; }
</style>
</head>
<body>
<div class="container">
<h1 class="mb-4">⚽ 禁区内射门统计对比</h1>
<!-- 比赛选择 -->
<div class="card p-3 mb-4">
<form method="GET" class="row g-3">
<div class="col-md-6">
<label for="match_id" class="form-label">选择比赛</label>
<select name="match_id" id="match_id" class="form-select" onchange="this.form.submit()">
<?php foreach ($matches as $match): ?>
<option value="<?= $match['id'] ?>" <?= $selectedMatch == $match['id'] ? 'selected' : '' ?>>
<?= $match['home_team'] ?> vs <?= $match['away_team'] ?> (<?= date('Y-m-d', strtotime($match['match_date'])) ?>)
</option>
<?php endforeach; ?>
</select>
</div>
</form>
</div>
<?php if ($selectedMatch): ?>
<?php $matchStats = $stats->getPenaltyAreaShotsByMatch($selectedMatch); ?>
<!-- 射门对比图表 -->
<div class="card p-4">
<h4 class="mb-3">禁区内射门对比</h4>
<div class="row">
<div class="col-md-8">
<canvas id="shotChart"></canvas>
</div>
<div class="col-md-4">
<?php foreach ($matchStats as $team): ?>
<div class="mb-3 p-3 border rounded">
<h5><?= $team['team_name'] ?></h5>
<div class="mb-2">禁区内射门: <strong><?= $team['area_shots'] ?? 0 ?></strong> 次</div>
<div class="mb-2">禁区外射门: <strong><?= $team['outside_shots'] ?? 0 ?></strong> 次</div>
<div class="mb-2">禁区内进球: <strong class="text-success"><?= $team['area_goals'] ?? 0 ?></strong> 个</div>
<div class="progress mb-2">
<div class="progress-bar bg-success" style="width: <?= $team['total_shots'] > 0 ? ($team['area_shots'] / $team['total_shots'] * 100) : 0 ?>%">
<?= $team['total_shots'] > 0 ? round($team['area_shots'] / $team['total_shots'] * 100) : 0 ?>%
</div>
</div>
<small class="text-muted">禁区内射门占比</small>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<!-- 射门时间分布 -->
<div class="card p-4 mt-4">
<h4>射门时间分布</h4>
<canvas id="timeChart" width="400" height="200"></canvas>
</div>
<!-- 统计数据表 -->
<div class="card p-4 mt-4">
<h4>详细统计</h4>
<table class="table table-striped">
<thead>
<tr>
<th>球队</th>
<th>总射门</th>
<th>禁区内射门</th>
<th>禁区外射门</th>
<th>禁区内进球</th>
<th>禁区射门转化率</th>
</tr>
</thead>
<tbody>
<?php foreach ($matchStats as $team): ?>
<tr>
<td><?= $team['team_name'] ?></td>
<td><?= $team['total_shots'] ?></td>
<td class="text-success"><?= $team['area_shots'] ?? 0 ?></td>
<td><?= $team['outside_shots'] ?? 0 ?></td>
<td><?= $team['area_goals'] ?? 0 ?></td>
<td>
<?= $team['area_shots'] > 0 ? number_format($team['area_goals'] / $team['area_shots'] * 100, 2) : 0 ?>%
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
// 射门对比图表
const matchStats = <?= json_encode($matchStats) ?>;
const ctx1 = document.getElementById('shotChart').getContext('2d');
new Chart(ctx1, {
type: 'bar',
data: {
labels: matchStats.map(t => t.team_name),
datasets: [
{
label: '禁区内射门',
data: matchStats.map(t => t.area_shots || 0),
backgroundColor: 'rgba(40, 167, 69, 0.7)',
borderColor: 'rgba(40, 167, 69, 1)',
borderWidth: 1
},
{
label: '禁区外射门',
data: matchStats.map(t => t.outside_shots || 0),
backgroundColor: 'rgba(255, 193, 7, 0.7)',
borderColor: 'rgba(255, 193, 7, 1)',
borderWidth: 1
}
]
},
options: {
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: '射门次数'
}
}
},
plugins: {
title: {
display: true,
text: '球队射门分布对比'
}
}
}
});
</script>
<?php endif; ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
赛季统计数据
// season_stats.php - 赛季禁区内射门统计
<?php
require_once 'config.php';
require_once 'ShotStatistics.php';
$stats = new ShotStatistics();
$seasonStats = $stats->getSeasonPenaltyAreaStats(null, '2024-01-01', '2024-12-31');
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">赛季禁区内射门统计</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
<h2>2024赛季禁区内射门统计</h2>
<div class="card p-4">
<table class="table table-hover">
<thead>
<tr>
<th>排名</th>
<th>球队</th>
<th>总射门</th>
<th>禁区内射门</th>
<th>禁区内进球</th>
<th>禁区射门占比</th>
<th>禁区进球转化率</th>
</tr>
</thead>
<tbody>
<?php $rank = 1; ?>
<?php foreach ($seasonStats as $stat): ?>
<tr>
<td><?= $rank++ ?></td>
<td><?= $stat['team_name'] ?></td>
<td><?= $stat['total_shots'] ?></td>
<td><?= $stat['area_shots'] ?></td>
<td><?= $stat['area_goals'] ?></td>
<td><?= $stat['area_shot_percentage'] ?>%</td>
<td><?= $stat['area_conversion_rate'] ?>%</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>
数据导入示例
// import_shots_data.php - 数据导入示例
<?php
require_once 'ShotStatistics.php';
function importShotData($matchId, $shots) {
$db = getConnection();
$insertSql = "INSERT INTO shots (match_id, team_id, player_id, shot_time, is_penalty_area, is_goal, shot_type, x_coordinate, y_coordinate)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $db->prepare($insertSql);
foreach ($shots as $shot) {
$stmt->execute([
$matchId,
$shot['team_id'],
$shot['player_id'],
$shot['shot_time'],
$shot['is_penalty_area'],
$shot['is_goal'],
$shot['shot_type'],
$shot['x_coordinate'],
$shot['y_coordinate']
]);
}
echo "成功导入 " . count($shots) . " 条射门数据";
}
?>
使用说明
- 配置数据库: 执行提供的SQL语句创建表结构
- 设置连接: 修改
config.php中的数据库连接信息 - 导入数据: 通过管理后台录入或批量导入射门数据
- 访问页面:
- 运行
compare_shots.php查看单场比赛对比 - 运行
season_stats.php查看赛季统计数据
- 运行
这个系统的特点:
- 支持多场比赛、多球队对比
- 提供可视化图表展示
- 可扩展性强,可以添加更多统计维度(如射门方向、射门方式等)
- 支持时间段筛选和历史数据对比
你可以根据实际需求调整统计维度和展示方式,需要我添加其他功能吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播