php实现评分功能
数据库设计
创建数据库表存储评分数据,表结构可包含字段:id(主键)、item_id(被评分项ID)、user_id(用户ID)、score(分数)、created_at(评分时间)。示例SQL:
CREATE TABLE ratings (
id INT AUTO_INCREMENT PRIMARY KEY,
item_id INT NOT NULL,
user_id INT NOT NULL,
score TINYINT NOT NULL CHECK (score BETWEEN 1 AND 5),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
评分表单
前端使用HTML表单提交评分,限制分数范围为1-5星。表单需包含CSRF防护:
<form action="rate.php" method="post">
<input type="hidden" name="item_id" value="123">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<select name="score">
<option value="1">1星</option>
<option value="5">5星</option>
</select>
<button type="submit">提交评分</button>
</form>
后端处理
PHP接收表单数据并验证,防止重复评分:
// rate.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF验证失败');
}
$itemId = (int)$_POST['item_id'];
$score = (int)$_POST['score'];
$userId = $_SESSION['user_id'] ?? 0;
// 验证分数范围
if ($score < 1 || $score > 5) {
die('无效评分');
}
// 检查是否已评分
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT id FROM ratings WHERE item_id = ? AND user_id = ?');
$stmt->execute([$itemId, $userId]);
if ($stmt->fetch()) {
die('您已评分');
}
// 插入新评分
$stmt = $pdo->prepare('INSERT INTO ratings (item_id, user_id, score) VALUES (?, ?, ?)');
$stmt->execute([$itemId, $userId, $score]);
header('Location: item.php?id='.$itemId);
}
显示平均分
计算并显示项目平均评分:
// item.php
$itemId = (int)$_GET['id'];
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
// 获取平均分
$stmt = $pdo->prepare('SELECT AVG(score) as avg_score FROM ratings WHERE item_id = ?');
$stmt->execute([$itemId]);
$avgScore = round($stmt->fetch()['avg_score'], 1);
echo "当前评分: {$avgScore}星";
星级显示
使用HTML/CSS显示星级评分:
<div class="stars">
<?php for ($i = 1; $i <= 5; $i++): ?>
<span class="star <?= $i <= round($avgScore) ? 'filled' : '' ?>">★</span>
<?php endfor; ?>
</div>
<style>
.star { color: #ccc; font-size: 24px; }
.star.filled { color: #ffcc00; }
</style>
防止刷分
添加IP限制和频率控制:
// 在rate.php中追加
$ip = $_SERVER['REMOTE_ADDR'];
$stmt = $pdo->prepare('SELECT COUNT(*) FROM ratings WHERE ip = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)');
$stmt->execute([$ip]);
if ($stmt->fetchColumn() > 10) {
die('评分过于频繁');
}






