php实现抽奖
PHP实现抽奖功能
抽奖功能的核心在于概率分配和随机数生成。以下是实现抽奖功能的几种常见方法:
权重抽奖法
权重抽奖法根据奖品的中奖概率设置权重,通过随机数判断中奖结果:

function lotteryByWeight($prizes) {
$totalWeight = array_sum(array_column($prizes, 'weight'));
$rand = mt_rand(1, $totalWeight);
$currentWeight = 0;
foreach ($prizes as $prize) {
$currentWeight += $prize['weight'];
if ($rand <= $currentWeight) {
return $prize;
}
}
return null;
}
// 示例奖品配置
$prizes = [
['id' => 1, 'name' => '一等奖', 'weight' => 1],
['id' => 2, 'name' => '二等奖', 'weight' => 5],
['id' => 3, 'name' => '三等奖', 'weight' => 10],
['id' => 4, 'name' => '谢谢参与', 'weight' => 84]
];
概率抽奖法
直接使用概率百分比进行抽奖:
function lotteryByProbability($prizes) {
$rand = mt_rand(1, 10000) / 100; // 保留两位小数
$currentProbability = 0;
foreach ($prizes as $prize) {
$currentProbability += $prize['probability'];
if ($rand <= $currentProbability) {
return $prize;
}
}
return null;
}
// 示例奖品配置
$prizes = [
['id' => 1, 'name' => '一等奖', 'probability' => 0.1],
['id' => 2, 'name' => '二等奖', 'probability' => 0.5],
['id' => 3, 'name' => '三等奖', 'probability' => 1],
['id' => 4, 'name' => '谢谢参与', 'probability' => 98.4]
];
数据库实现抽奖
对于需要从数据库读取奖品信息的场景:

function lotteryFromDB($pdo) {
$stmt = $pdo->query("SELECT id, name, probability FROM prizes WHERE status = 1");
$prizes = $stmt->fetchAll(PDO::FETCH_ASSOC);
$rand = mt_rand(1, 10000) / 100;
$currentProbability = 0;
foreach ($prizes as $prize) {
$currentProbability += $prize['probability'];
if ($rand <= $currentProbability) {
return $prize;
}
}
return ['id' => 0, 'name' => '谢谢参与'];
}
防止重复中奖
对于需要限制用户重复中奖的场景:
function checkUserLottery($userId, $pdo) {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM lottery_records WHERE user_id = ? AND prize_id > 0 AND created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)");
$stmt->execute([$userId]);
$count = $stmt->fetchColumn();
return $count == 0;
}
function recordLottery($userId, $prizeId, $pdo) {
$stmt = $pdo->prepare("INSERT INTO lottery_records (user_id, prize_id, created_at) VALUES (?, ?, NOW())");
return $stmt->execute([$userId, $prizeId]);
}
可视化抽奖效果
实现前端转盘效果配合后端API:
// API接口
header('Content-Type: application/json');
try {
$userId = $_SESSION['user_id'] ?? 0;
$pdo = new PDO('mysql:host=localhost;dbname=lottery', 'username', 'password');
if (!checkUserLottery($userId, $pdo)) {
echo json_encode(['code' => 0, 'msg' => '您今天已经抽过奖了']);
exit;
}
$prize = lotteryFromDB($pdo);
recordLottery($userId, $prize['id'], $pdo);
echo json_encode(['code' => 1, 'data' => $prize]);
} catch (Exception $e) {
echo json_encode(['code' => 0, 'msg' => '系统错误']);
}
注意事项
- 概率总和应为100%,确保逻辑严谨
- 使用mt_rand()而非rand(),因为前者随机性更好
- 对于高并发场景,考虑使用Redis等缓存系统
- 重要抽奖结果应记录日志,防止纠纷
- 前端应显示抽奖动画,增强用户体验
以上方法可根据实际业务需求进行组合和调整。权重法和概率法本质相同,只是数据表示方式不同。数据库实现适合奖品经常变动的场景,而硬编码适合奖品固定的场景。






