我将为您设计一个PHP勋章自动发放系统,包含完整的逻辑和代码实现。

勋章自动发放系统设计
数据库设计
-- 勋章表 CREATE TABLE `badges` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL COMMENT '勋章名称', `code` varchar(50) NOT NULL COMMENT '勋章唯一标识', `description` varchar(255) DEFAULT NULL COMMENT '勋章描述', `icon` varchar(255) DEFAULT NULL COMMENT '勋章图标路径', `conditions` text NOT NULL COMMENT '发放条件(JOSN格式)', `status` tinyint(1) DEFAULT '1' COMMENT '状态:1启用 0禁用', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `unique_code` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 用户勋章表 CREATE TABLE `user_badges` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '用户ID', `badge_id` int(11) NOT NULL COMMENT '勋章ID', `earned_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '获得时间', `source` varchar(50) DEFAULT NULL COMMENT '获得来源', PRIMARY KEY (`id`), UNIQUE KEY `unique_user_badge` (`user_id`, `badge_id`), KEY `idx_user_id` (`user_id`), KEY `idx_badge_id` (`badge_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 用户操作日志表(用于统计) CREATE TABLE `user_actions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `action_type` varchar(50) NOT NULL COMMENT '操作类型', `action_data` text DEFAULT NULL COMMENT '操作数据(JSON)', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_action` (`user_id`, `action_type`), KEY `idx_created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
核心类实现
<?php
class BadgeManager {
private $db;
private $cache;
public function __construct($db, $cache = null) {
$this->db = $db;
$this->cache = $cache ?: new RedisCache(); // 或者使用文件缓存
}
/**
* 检查并发放勋章
*/
public function checkAndAward($userId, $actionType = null) {
// 获取所有启用的勋章
$badges = $this->getAllEnabledBadges();
$awardedBadges = [];
foreach ($badges as $badge) {
// 跳过已获得的勋章
if ($this->hasBadge($userId, $badge['id'])) {
continue;
}
// 解析条件并检查
$conditions = json_decode($badge['conditions'], true);
if ($this->checkConditions($userId, $badge, $conditions, $actionType)) {
$this->awardBadge($userId, $badge['id'], $actionType);
$awardedBadges[] = $badge;
}
}
return $awardedBadges;
}
/**
* 获取所有启用的勋章
*/
private function getAllEnabledBadges() {
$cacheKey = 'all_enabled_badges';
$badges = $this->cache->get($cacheKey);
if (!$badges) {
$sql = "SELECT * FROM badges WHERE status = 1";
$result = $this->db->query($sql);
$badges = $result->fetch_all(MYSQLI_ASSOC);
$this->cache->set($cacheKey, $badges, 3600); // 缓存1小时
}
return $badges;
}
/**
* 检查用户是否已获得某勋章
*/
private function hasBadge($userId, $badgeId) {
$sql = "SELECT COUNT(*) as count FROM user_badges
WHERE user_id = ? AND badge_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("ii", $userId, $badgeId);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
return $row['count'] > 0;
}
/**
* 发放勋章
*/
private function awardBadge($userId, $badgeId, $source) {
$sql = "INSERT INTO user_badges (user_id, badge_id, source)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE id = id";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("iis", $userId, $badgeId, $source);
$stmt->execute();
// 清除缓存
$this->clearUserCache($userId);
// 触发通知
$this->notifyUser($userId, $badgeId);
}
/**
* 检查发放条件
*/
private function checkConditions($userId, $badge, $conditions, $actionType) {
foreach ($conditions as $condition) {
$result = $this->checkSingleCondition($userId, $badge, $condition);
if (!$result) {
return false;
}
}
return true;
}
/**
* 检查单个条件
*/
private function checkSingleCondition($userId, $badge, $condition) {
$type = $condition['type'];
$value = $condition['value'];
switch ($type) {
case 'action_count':
return $this->checkActionCount($userId, $condition['action_type'], $value);
case 'continuous_days':
return $this->checkContinuousDays($userId, $value);
case 'total_days':
return $this->checkTotalDays($userId, $value);
case 'points':
return $this->checkPoints($userId, $value);
case 'level':
return $this->checkUserLevel($userId, $value);
case 'invite_count':
return $this->checkInviteCount($userId, $value);
case 'special_action':
return $this->checkSpecialAction($userId, $condition['action_type']);
default:
return false;
}
}
/**
* 检查操作次数
*/
private function checkActionCount($userId, $actionType, $requiredCount) {
$cacheKey = "user_action_count_{$userId}_{$actionType}";
$count = $this->cache->get($cacheKey);
if ($count === false) {
$sql = "SELECT COUNT(*) as count FROM user_actions
WHERE user_id = ? AND action_type = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("is", $userId, $actionType);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$count = $row['count'];
$this->cache->set($cacheKey, $count, 600);
}
return $count >= $requiredCount;
}
/**
* 检查连续签到天数
*/
private function checkContinuousDays($userId, $requiredDays) {
$sql = "SELECT created_at FROM user_actions
WHERE user_id = ? AND action_type = 'daily_checkin'
ORDER BY created_at DESC LIMIT ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("ii", $userId, $requiredDays);
$stmt->execute();
$result = $stmt->get_result();
$dates = [];
while ($row = $result->fetch_assoc()) {
$dates[] = date('Y-m-d', strtotime($row['created_at']));
}
if (count($dates) < $requiredDays) {
return false;
}
// 检查是否连续
$start = strtotime($dates[0]);
$expectedDate = $start;
foreach ($dates as $date) {
if (strtotime($date) != $expectedDate) {
return false;
}
$expectedDate = strtotime('+1 day', $expectedDate);
}
return true;
}
/**
* 检查总活跃天数
*/
private function checkTotalDays($userId, $requiredDays) {
$sql = "SELECT COUNT(DISTINCT DATE(created_at)) as days
FROM user_actions WHERE user_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
return $row['days'] >= $requiredDays;
}
/**
* 检查积分
*/
private function checkPoints($userId, $requiredPoints) {
$sql = "SELECT points FROM user_points WHERE user_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
return $row && $row['points'] >= $requiredPoints;
}
/**
* 检查用户等级
*/
private function checkUserLevel($userId, $requiredLevel) {
$sql = "SELECT level FROM user_levels WHERE user_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
return $row && $row['level'] >= $requiredLevel;
}
/**
* 清除用户缓存
*/
private function clearUserCache($userId) {
$this->cache->delete("user_badges_{$userId}");
$this->cache->delete("user_action_count_{$userId}_*");
}
/**
* 通知用户获得勋章
*/
private function notifyUser($userId, $badgeId) {
// 发送通知(邮件、短信、站内消息等)
$badge = $this->getBadgeById($badgeId);
$message = "恭喜你获得了【{$badge['name']}】勋章!";
// 这里可以实现通知逻辑
NotificationHelper::send($userId, $message);
}
}
事件触发器
<?php
class BadgeEventTrigger {
private $badgeManager;
public function __construct($db) {
$this->badgeManager = new BadgeManager($db);
}
/**
* 用户完成某个操作时触发
*/
public function onAction($userId, $actionType, $actionData = null) {
// 记录操作日志
$this->logAction($userId, $actionType, $actionData);
// 检查勋章
$awarded = $this->badgeManager->checkAndAward($userId, $actionType);
// 返回新获得的勋章
return $awarded;
}
/**
* 用户注册时
*/
public function onRegister($userId) {
// 用户注册奖励
$this->logAction($userId, 'register', []);
return $this->badgeManager->checkAndAward($userId, 'register');
}
/**
* 用户每日签到
*/
public function onDailyCheckin($userId) {
$this->logAction($userId, 'daily_checkin', []);
return $this->badgeManager->checkAndAward($userId, 'daily_checkin');
}
/**
* 用户完成任务
*/
public function onTaskComplete($userId, $taskId) {
$this->logAction($userId, 'task_complete', ['task_id' => $taskId]);
return $this->badgeManager->checkAndAward($userId, 'task_complete');
}
/**
* 记录用户操作
*/
private function logAction($userId, $actionType, $actionData) {
$sql = "INSERT INTO user_actions (user_id, action_type, action_data)
VALUES (?, ?, ?)";
$stmt = $this->db->prepare($sql);
$data = json_encode($actionData);
$stmt->bind_param("iss", $userId, $actionType, $data);
$stmt->execute();
}
}
勋章配置示例
// 勋章配置示例
$badgeConfigs = [
[
'name' => '新手勋章',
'code' => 'newbie',
'description' => '注册成为新用户',
'conditions' => [
['type' => 'action_count', 'action_type' => 'register', 'value' => 1]
]
],
[
'name' => '签到达人',
'code' => 'checkin_master',
'description' => '连续签到7天',
'conditions' => [
['type' => 'continuous_days', 'value' => 7]
]
],
[
'name' => '活跃分子',
'code' => 'active_member',
'description' => '累计活跃30天',
'conditions' => [
['type' => 'total_days', 'value' => 30]
]
],
[
'name' => '积分高手',
'code' => 'points_master',
'description' => '积分达到1000分',
'conditions' => [
['type' => 'points', 'value' => 1000]
]
],
[
'name' => '任务达人',
'code' => 'task_master',
'description' => '完成10个任务',
'conditions' => [
['type' => 'action_count', 'action_type' => 'task_complete', 'value' => 10]
]
],
[
'name' => '魅力之星',
'code' => 'popular',
'description' => '成功邀请5位好友',
'conditions' => [
['type' => 'invite_count', 'value' => 5]
]
]
];
使用示例
// 初始化
$db = new mysqli('localhost', 'username', 'password', 'database');
$trigger = new BadgeEventTrigger($db);
// 用户注册时
$userId = 123;
$newBadges = $trigger->onRegister($userId);
// 用户完成操作时
$newBadges = $trigger->onAction($userId, 'post_create', ['content' => '...']);
// 每日签到
$newBadges = $trigger->onDailyCheckin($userId);
// 完成任务
$newBadges = $trigger->onTaskComplete($userId, 456);
// 手动检查和发放(定时任务)
$badgeManager = new BadgeManager($db);
$allUsers = $badgeManager->getAllActiveUsers();
foreach ($allUsers as $user) {
$badgeManager->checkAndAward($user['id']);
}
扩展功能
// 添加定时检查任务
$schedule = new Schedule([
'daily' => function() {
// 每天凌晨执行
$badgeManager = new BadgeManager($db);
// 检查特殊勋章
$badgeManager->checkSpecialBadge();
},
'hourly' => function() {
// 每小时执行
$badgeManager->checkTimeBasedBadges();
}
]);
// 添加通知功能
class BadgeNotification {
public static function send($userId, $badgeName) {
// 站内信
Message::create($userId, "获得新勋章:$badgeName");
// 推送通知(可选)
PushNotification::send($userId, "恭喜获得 $badgeName 勋章!");
}
}
这个系统设计包含:
- 灵活的勋章条件配置
- 自动发放和手动检查
- 缓存优化性能
- 用户通知功能
- 可扩展的事件触发机制
您可以根据具体需求调整条件类型和发放逻辑。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播