
本文讲解如何正确从数据库读取用户经验值(userexp),依据预设等级规则计算对应等级(userlvl),并安全地更新会话与数据库,避免因执行顺序、变量初始化或 sql 注入导致的逻辑失效。
本文讲解如何正确从数据库读取用户经验值(userexp),依据预设等级规则计算对应等级(userlvl),并安全地更新会话与数据库,避免因执行顺序、变量初始化或 sql 注入导致的逻辑失效。
在 PHP Web 应用中,根据数据库中的数值(如用户经验值 userexp)动态计算并设置等级变量(如 userlvl),是常见需求。但原始代码存在多个关键问题:变量未从数据库读取就直接赋默认值、等级判断逻辑在查询前执行、SQL 语句未实际执行查询、缺少错误处理与防注入措施,导致无论数据库中 userexp 是多少,$_SESSION['userlvl'] 始终为 1。
以下是推荐的完整、安全、可维护的实现方案:
✅ 正确流程:查 → 算 → 存 → 用
<?php session_start();
// 1. 数据库连接(请替换为你的实际配置)
$host = 'localhost';
$dbname = 'your_db';
$username = 'your_user';
$password = 'your_pass';
$conn = new mysqli($host, $username, $password, $dbname);
if ($conn->connect_error) {
die("数据库连接失败: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4"); // 防止中文/特殊字符问题
// 2. 从数据库获取当前用户的 userexp(务必使用预处理语句防止 SQL 注入)
if (!isset($_SESSION['userid'])) {
die("用户未登录");
}
$stmt = $conn->prepare("SELECT userexp FROM users WHERE userid = ?");
$stmt->bind_param("i", $_SESSION['userid']);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
die("用户不存在");
}
$userData = $result->fetch_assoc();
$userexp = (int)$userData['userexp'];
// 3. 根据经验值计算等级(优化:使用降序数组 + 循环,比长 if-else 更清晰可维护)
$levelThresholds = [
[27586350412, 50],
[22069080330, 50], // 注意:此值 = $threshold[0]) {
$userlvl = $threshold[1];
break;
}
}
// 4. 同步更新数据库(可选,但推荐:确保 DB 与会话状态一致)
$stmt = $conn->prepare("UPDATE users SET userlevel = ? WHERE userid = ?");
$stmt->bind_param("ii", $userlvl, $_SESSION['userid']);
$stmt->execute();
// 5. 更新会话变量,供后续页面使用
$_SESSION['userlvl'] = $userlvl;
$_SESSION['userexp'] = $userexp;
// 6. 关闭连接
$stmt->close();
$conn->close();
?>
? 关键注意事项
- 绝不硬编码 SQL 拼接:原始代码中 $query = ("SELECT * FROM users WHERE userexp='$userexp'") 是严重安全隐患(SQL 注入)且逻辑错误($userexp 还未从 DB 获取)。必须使用 prepare() + bind_param()。
- 执行顺序至关重要:先 SELECT 获取真实数据,再计算等级,最后 UPDATE 和写入 $_SESSION。原始代码把 $userexp = 0 放在查询前,导致所有判断都基于 0。
- 等级阈值建议重构:原始 50+ 层 if-else 易出错、难维护。改用关联数组或数据库配置表(如 level_rules(threshold, level))更专业。
- 类型强制转换:$userexp = (int)$userData['userexp'] 避免字符串比较引发的意外(如 '100' >= '20' 为 false)。
- 会话与数据库双写一致性:更新 $_SESSION 的同时,也更新数据库字段(如 userlevel),防止会话过期后丢失等级状态。
✅ 最终使用(在 HTML 中)
<td> <b>LVL:</b> <?php echo htmlspecialchars($_SESSION['userlvl']); ?> </td>
? 提示:htmlspecialchars() 防止 XSS;若需更高安全性,可对 userlvl 做整数校验(is_int($_SESSION['userlvl']) && $_SESSION['userlvl'] >= 1)。
通过以上结构化实现,你将获得一个健壮、安全、易于调试和扩展的等级系统——即使作为兼职项目,也能为未来功能(如等级徽章、权限控制)打下坚实基础。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











