本文目录导读:

我来介绍几种PHP实现幸运抽奖的常见方案,从简单到复杂逐步实现。
基础随机抽奖(最简单方案)
<?php
// 基础随机抽奖
function basicLottery($participants) {
$winner = $participants[array_rand($participants)];
return $winner;
}
// 使用示例
$users = ['用户A', '用户B', '用户C', '用户D', '用户E'];
$winner = basicLottery($users);
echo "中奖者:{$winner}";
?>
权重抽奖(按概率分配)
<?php
class WeightedLottery {
private $prizes = [];
public function addPrize($name, $weight) {
$this->prizes[] = [
'name' => $name,
'weight' => $weight
];
}
public function draw() {
$totalWeight = array_sum(array_column($this->prizes, 'weight'));
$random = mt_rand(1, $totalWeight * 100) / 100;
$currentWeight = 0;
foreach ($this->prizes as $prize) {
$currentWeight += $prize['weight'];
if ($random <= $currentWeight) {
return $prize['name'];
}
}
return null;
}
}
// 使用示例
$lottery = new WeightedLottery();
$lottery->addPrize('一等奖(iPhone)', 1); // 1%概率
$lottery->addPrize('二等奖(耳机)', 10); // 10%概率
$lottery->addPrize('三等奖(优惠券)', 30); // 30%概率
$lottery->addPrize('谢谢参与', 59); // 59%概率
$result = $lottery->draw();
echo "恭喜获得:{$result}";
?>
完整的抽奖系统(含数据库操作)
<?php
// 数据库配置文件 config.php
define('DB_HOST', 'localhost');
define('DB_NAME', 'lottery_db');
define('DB_USER', 'root');
define('DB_PASS', 'password');
// 抽奖系统主类
class LotterySystem {
private $db;
private $userId;
public function __construct($userId) {
$this->userId = $userId;
$this->connectDB();
}
private function connectDB() {
try {
$this->db = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
DB_USER,
DB_PASS
);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("数据库连接失败:" . $e->getMessage());
}
}
// 检查抽奖资格
private function checkEligibility() {
$today = date('Y-m-d');
$stmt = $this->db->prepare(
"SELECT COUNT(*) FROM lottery_records
WHERE user_id = ? AND DATE(created_at) = ?"
);
$stmt->execute([$this->userId, $today]);
return $stmt->fetchColumn() == 0; // 每人每天限抽一次
}
// 获取奖品配置
private function getPrizes() {
$stmt = $this->db->query("SELECT * FROM prizes WHERE status = 1");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 执行抽奖
public function draw() {
// 检查资格
if (!$this->checkEligibility()) {
return ['success' => false, 'message' => '今日已抽奖,请明天再来'];
}
// 获取奖品
$prizes = $this->getPrizes();
if (empty($prizes)) {
return ['success' => false, 'message' => '暂无可用奖品'];
}
// 权重抽奖逻辑
$totalWeight = array_sum(array_column($prizes, 'weight'));
$random = mt_rand(1, $totalWeight);
$currentWeight = 0;
$winPrize = null;
foreach ($prizes as $prize) {
$currentWeight += $prize['weight'];
if ($random <= $currentWeight) {
$winPrize = $prize;
break;
}
}
// 记录抽奖结果
$this->recordLottery($winPrize);
// 更新库存
$this->updateStock($winPrize);
return [
'success' => true,
'prize' => $winPrize['name'],
'level' => $winPrize['level']
];
}
private function recordLottery($prize) {
$stmt = $this->db->prepare(
"INSERT INTO lottery_records (user_id, prize_id, prize_name, created_at)
VALUES (?, ?, ?, NOW())"
);
$stmt->execute([
$this->userId,
$prize['id'],
$prize['name']
]);
}
private function updateStock($prize) {
$stmt = $this->db->prepare(
"UPDATE prizes SET stock = stock - 1
WHERE id = ? AND stock > 0"
);
$stmt->execute([$prize['id']]);
}
// 获取用户抽奖记录
public function getRecords($limit = 10) {
$stmt = $this->db->prepare(
"SELECT * FROM lottery_records
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT ?"
);
$stmt->execute([$this->userId, $limit]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
// 使用示例
$userId = 123; // 当前用户ID
$lottery = new LotterySystem($userId);
$result = $lottery->draw();
if ($result['success']) {
echo "🎉 恭喜获得:{$result['prize']}";
} else {
echo "❌ {$result['message']}";
}
?>
数据库表结构
-- 奖品表
CREATE TABLE `prizes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT '奖品名称',
`level` int(11) NOT NULL COMMENT '奖项等级',
`weight` int(11) NOT NULL COMMENT '权重',
`stock` int(11) NOT NULL DEFAULT 0 COMMENT '库存',
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 抽奖记录表
CREATE TABLE `lottery_records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户ID',
`prize_id` int(11) DEFAULT NULL COMMENT '奖品ID',
`prize_name` varchar(100) DEFAULT NULL COMMENT '奖品名称',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入测试数据
INSERT INTO `prizes` (`name`, `level`, `weight`, `stock`) VALUES
('一等奖 iPhone 15', 1, 1, 3),
('二等奖 AirPods', 2, 5, 20),
('三等奖 50元优惠券', 3, 20, 100),
('四等奖 10元优惠券', 4, 30, 500),
('谢谢参与', 5, 44, 99999);
前端抽奖页面示例
<!DOCTYPE html>
<html>
<head>幸运抽奖</title>
<style>
.lottery-container {
text-align: center;
padding: 50px;
}
.prize-box {
width: 300px;
height: 300px;
border: 3px solid #ffd700;
border-radius: 10px;
margin: 20px auto;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
cursor: pointer;
transition: transform 0.3s;
}
.prize-box:hover {
transform: scale(1.05);
}
.prize-box.spinning {
animation: spin 0.5s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
25% { transform: rotate(5deg); }
75% { transform: rotate(-5deg); }
100% { transform: rotate(0deg); }
}
.btn-draw {
padding: 15px 30px;
font-size: 18px;
background: #ff4757;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.btn-draw:disabled {
background: #ccc;
cursor: not-allowed;
}
.result {
margin: 20px 0;
font-size: 20px;
}
</style>
</head>
<body>
<div class="lottery-container">
<h1>🎰 幸运大转盘</h1>
<div class="prize-box" id="prizeBox">
点击抽奖
</div>
<div class="result" id="result"></div>
<button class="btn-draw" id="drawBtn" onclick="draw()">开始抽奖</button>
<!-- 历史记录 -->
<div style="margin-top: 50px;">
<h3>抽奖记录</h3>
<table border="1" style="margin: auto;">
<tr>
<th>时间</th>
<th>奖品</th>
</tr>
<?php foreach ($lottery->getRecords() as $record): ?>
<tr>
<td><?php echo $record['created_at']; ?></td>
<td><?php echo $record['prize_name']; ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<script>
function draw() {
const btn = document.getElementById('drawBtn');
const box = document.getElementById('prizeBox');
const result = document.getElementById('result');
btn.disabled = true;
box.classList.add('spinning');
result.innerHTML = '抽奖中...';
// 发送AJAX请求
fetch('lottery_api.php?action=draw', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
setTimeout(() => {
box.classList.remove('spinning');
btn.disabled = false;
if (data.success) {
result.innerHTML = `🎉 恭喜获得:${data.prize}`;
box.style.background = 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)';
} else {
result.innerHTML = `😅 ${data.message}`;
}
}, 2000);
})
.catch(error => {
box.classList.remove('spinning');
btn.disabled = false;
result.innerHTML = '抽奖失败,请重试';
});
}
</script>
</body>
</html>
API接口文件 (lottery_api.php)
<?php
header('Content-Type: application/json');
session_start();
require_once 'LotterySystem.php';
$action = $_GET['action'] ?? '';
$userId = $_SESSION['user_id'] ?? 0;
if (!$userId) {
echo json_encode(['success' => false, 'message' => '请先登录']);
exit;
}
$lottery = new LotterySystem($userId);
switch ($action) {
case 'draw':
$result = $lottery->draw();
echo json_encode($result);
break;
case 'records':
$records = $lottery->getRecords();
echo json_encode(['success' => true, 'records' => $records]);
break;
default:
echo json_encode(['success' => false, 'message' => '无效请求']);
}
?>
安全性和优化建议
<?php
// 1. 防刷机制
class AntiCheat {
// IP限制
public function checkIP() {
$ip = $_SERVER['REMOTE_ADDR'];
$key = "lottery_ip_{$ip}";
// Redis限流
$count = $redis->incr($key);
if ($count > 100) { // 每小时100次限制
die('操作过于频繁');
}
}
// 并发控制
public function lockUser($userId) {
$lockKey = "lottery_lock_{$userId}";
return $redis->setnx($lockKey, 1); // 分布式锁
}
public function unlockUser($userId) {
$lockKey = "lottery_lock_{$userId}";
$redis->del($lockKey);
}
}
// 2. 库存控制
function checkStockWithLock($prizeId) {
$db->beginTransaction();
try {
$stmt = $db->prepare("SELECT stock FROM prizes WHERE id = ? FOR UPDATE");
$stmt->execute([$prizeId]);
$stock = $stmt->fetchColumn();
if ($stock <= 0) {
throw new Exception('库存不足');
}
// 扣减库存
$stmt = $db->prepare("UPDATE prizes SET stock = stock - 1 WHERE id = ?");
$stmt->execute([$prizeId]);
$db->commit();
return true;
} catch (Exception $e) {
$db->rollBack();
return false;
}
}
?>
使用建议
- 初始化:配置数据库连接和奖品数据
- 安全性:添加验证码、登录检查、频率限制
- 性能优化:使用Redis缓存奖品配置
- 日志记录:记录所有抽奖操作,便于审计
- 奖品发放:中奖后及时发放奖品,避免争议
这个系统可以根据实际需求灵活调整,添加更多功能如:积分抽奖、活动管理、数据分析等。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播