本文目录导读:

我来帮你规划一个PHP投票系统的搭建方案,这是一个相对完整的系统设计,我会从基础架构到核心功能逐步说明。
系统基础架构
环境要求
- PHP 7.4+
- MySQL 5.7+
- Web服务器:Apache/Nginx
- 推荐框架:Laravel/ThinkPHP(或原生PHP)
数据库设计
-- 投票主题表 CREATE TABLE `votes` ( `id` int(11) NOT NULL AUTO_INCREMENT, varchar(200) NOT NULL COMMENT '投票标题', `description` text COMMENT '投票描述', `type` tinyint(1) DEFAULT '0' COMMENT '0单选 1多选', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `status` tinyint(1) DEFAULT '1' COMMENT '0关闭 1开启', `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ); -- 投票选项表 CREATE TABLE `vote_options` ( `id` int(11) NOT NULL AUTO_INCREMENT, `vote_id` int(11) NOT NULL, `option_name` varchar(100) NOT NULL COMMENT '选项名称', `votes_count` int(11) DEFAULT '0' COMMENT '得票数', `sort_order` int(3) DEFAULT '0' COMMENT '排序', PRIMARY KEY (`id`), FOREIGN KEY (`vote_id`) REFERENCES `votes`(`id`) ON DELETE CASCADE ); -- 投票记录表 CREATE TABLE `vote_records` ( `id` int(11) NOT NULL AUTO_INCREMENT, `vote_id` int(11) NOT NULL, `option_id` int(11) NOT NULL, `user_id` int(11) COMMENT '用户ID(可空,匿名投票)', `ip_address` varchar(45) COMMENT 'IP地址(防刷票)', `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `unique_vote` (`vote_id`, `user_id`, `ip_address`) );
核心功能实现
创建投票(Create.php)
<?php
// 简单原生PHP示例
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = $_POST['title'];
$options = $_POST['options']; // 数组
$type = $_POST['type'];
$start_time = $_POST['start_time'];
$end_time = $_POST['end_time'];
// 开启事务
$conn->begin_transaction();
try {
// 插入投票主表
$stmt = $conn->prepare("INSERT INTO votes (title, description, type, start_time, end_time) VALUES (?, ?, ?, ?, ?)");
$stmt->bind_param("ssiss", $title, $description, $type, $start_time, $end_time);
$stmt->execute();
$vote_id = $conn->insert_id;
// 插入选项
$stmt = $conn->prepare("INSERT INTO vote_options (vote_id, option_name, sort_order) VALUES (?, ?, ?)");
$order = 1;
foreach ($options as $option) {
$stmt->bind_param("isi", $vote_id, $option, $order++);
$stmt->execute();
}
$conn->commit();
echo json_encode(['success' => true, 'vote_id' => $vote_id]);
} catch (Exception $e) {
$conn->rollback();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
投票功能(Vote.php)
<?php
function castVote($vote_id, $option_ids, $user_info) {
// 1. 验证投票是否有效
$vote = checkVoteValid($vote_id);
if (!$vote) {
return ['error' => '投票已结束或不存在'];
}
// 2. 检查是否已投票(防止重复)
if (checkAlreadyVoted($vote_id, $user_info)) {
return ['error' => '您已经投过票了'];
}
// 3. 验证选项数量(单选/多选)
if ($vote['type'] == 0 && count($option_ids) > 1) {
return ['error' => '此为单选投票'];
}
// 4. 记录投票
$conn->begin_transaction();
try {
foreach ($option_ids as $option_id) {
// 插入投票记录
$stmt = $conn->prepare("INSERT INTO vote_records (vote_id, option_id, user_id, ip_address) VALUES (?, ?, ?, ?)");
$stmt->bind_param("iiis", $vote_id, $option_id, $user_info['id'], $_SERVER['REMOTE_ADDR']);
$stmt->execute();
// 更新选项得票数
$conn->query("UPDATE vote_options SET votes_count = votes_count + 1 WHERE id = $option_id");
}
$conn->commit();
return ['success' => true];
} catch (Exception $e) {
$conn->rollback();
return ['error' => '投票失败,请重试'];
}
}
查看结果(Results.php)
<?php
// 获取投票结果
function getVoteResults($vote_id) {
$vote = $conn->query("SELECT * FROM votes WHERE id = $vote_id")->fetch_assoc();
// 获取各选项得票
$options = $conn->query("
SELECT vo.*,
(vo.votes_count / total.total_votes * 100) as percentage
FROM vote_options vo
CROSS JOIN (
SELECT SUM(votes_count) as total_votes
FROM vote_options
WHERE vote_id = $vote_id
) total
WHERE vo.vote_id = $vote_id
ORDER BY vo.sort_order
");
// 总投票人数
$total_voters = $conn->query("
SELECT COUNT(DISTINCT user_id) as voters
FROM vote_records
WHERE vote_id = $vote_id
")->fetch_assoc()['voters'];
return [
'vote' => $vote,
'options' => $options,
'total_voters' => $total_voters
];
}
前端界面示例
<!-- 投票表单 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">投票系统</title>
<style>
.vote-container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
}
.vote-item {
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
}
.progress-bar {
height: 20px;
background: #e0e0e0;
border-radius: 10px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #4CAF50;
transition: width 0.3s;
}
.btn-vote {
background: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="vote-container">
<!-- 投票表单 -->
<form id="voteForm" onsubmit="submitVote(event)">
<h2>你最喜欢的编程语言是?</h2>
<div class="vote-item">
<label>
<input type="radio" name="option" value="1" required>
PHP
</label>
</div>
<div class="vote-item">
<label>
<input type="radio" name="option" value="2">
JavaScript
</label>
</div>
<div class="vote-item">
<label>
<input type="radio" name="option" value="3">
Python
</label>
</div>
<button type="submit" class="btn-vote">提交投票</button>
</form>
<!-- 实时结果 -->
<div id="results">
<h3>当前结果</h3>
<div class="vote-item">
<span>PHP</span>
<div class="progress-bar">
<div class="progress-fill" style="width: 45%;">45%</div>
</div>
<span>45票</span>
</div>
<!-- 更多选项... -->
</div>
</div>
<script>
function submitVote(event) {
event.preventDefault();
const formData = new FormData(event.target);
fetch('vote.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if(data.success) {
alert('投票成功!');
loadResults(); // 刷新结果
} else {
alert(data.error || '投票失败');
}
});
}
function loadResults() {
fetch('results.php?vote_id=1')
.then(response => response.json())
.then(data => {
// 更新结果展示
updateDisplay(data);
});
}
// 自动刷新(每10秒)
setInterval(loadResults, 10000);
</script>
</body>
</html>
安全防护措施
防刷票机制
// IP限制
function checkIPLimit($vote_id) {
$ip = $_SERVER['REMOTE_ADDR'];
$time_limit = date('Y-m-d H:i:s', strtotime('-1 hour'));
$count = $conn->query("
SELECT COUNT(*) as cnt
FROM vote_records
WHERE vote_id = $vote_id
AND ip_address = '$ip'
AND created_at > '$time_limit'
")->fetch_assoc()['cnt'];
return $count < 3; // 每小时最多3次
}
// 验证码(Google reCAPTCHA)
function verifyCaptcha($token) {
$secret = 'YOUR_SECRET_KEY';
$response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$token");
$data = json_decode($response);
return $data->success;
}
SQL注入防护
// 使用预处理语句
$stmt = $conn->prepare("SELECT * FROM votes WHERE id = ?");
$stmt->bind_param("i", $vote_id);
$stmt->execute();
// 输入过滤
$title = htmlspecialchars(strip_tags($_POST['title']), ENT_QUOTES, 'UTF-8');
进阶功能扩展
- 用户系统集成:对接用户登录体系,支持实名投票
- 多语言支持:使用gettext或PHP数组实现国际化
- 图表展示:集成Chart.js或ECharts生成可视化结果
- 定时任务:使用cron或Laravel Task Scheduling自动关闭投票
- 数据分析:记录投票时间分布,分析用户行为
- 导出功能:支持CSV/Excel导出投票数据
部署建议
# Nginx配置示例
server {
listen 80;
server_name vote.yourdomain.com;
root /var/www/vote-system/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
这个方案涵盖了一个完整投票系统的基本功能,根据实际需求,你可以选择使用框架(推荐Laravel)来快速开发,或者基于原生PHP构建轻量级系统,记得在生产环境中做好性能优化和安全防护。