为何MySQL查询结果存入$_SESSION后显示为mysqli_result对象而非预期数值?
解决PHP登录验证中$_SESSION['roleid']返回mysqli_result对象而非数值的问题
嘿,我一眼就看出问题所在了——你直接把mysqli_query()返回的结果集对象赋值给了$_SESSION['roleid'],但这个对象并不是你要的数值,得从里面提取实际的role_id才行!
问题根源
mysqli_query()执行查询后,返回的是一个mysqli_result类型的对象,它代表了数据库查询的结果集合,而不是直接的字段值。你需要通过fetch方法从这个结果集里取出具体的数据。
快速修复方案
针对你现有的代码,只需要修改处理$result2的部分:
// 原来的错误代码:直接把结果集对象存session // $_SESSION['roleid'] = $result2; // 修改为:先从结果集中取出数据 if ($row2 = mysqli_fetch_assoc($result2)) { // 取出roles表的id字段值存入session $_SESSION['roleid'] = $row2['id']; } else { // 如果没查到对应角色,跳转到错误页 header("Location: ../index.php?login=error"); exit(); }
或者如果你习惯用索引数组,可以用mysqli_fetch_row():
if ($row2 = mysqli_fetch_row($result2)) { $_SESSION['roleid'] = $row2[0]; // 第一个字段就是roles.id }
更优的代码优化建议
除了修复这个问题,你的代码还有几个可以优化的地方,兼顾安全性和效率:
合并SQL查询,减少数据库请求
你现在用了两个查询,其实可以通过JOIN合并成一个,一次查询拿到用户信息和角色ID:$sql = "SELECT u.id, u.name, u.email, r.id as role_id FROM users u JOIN roles r ON u.role_id = r.id WHERE u.email = ? AND u.password = ?";杜绝SQL注入风险
你当前直接把POST参数拼进SQL语句,非常容易遭到SQL注入攻击。一定要用预处理语句:// 初始化预处理语句 $stmt = mysqli_prepare($conn, $sql); // 绑定参数(s代表字符串,两个参数都是字符串类型) mysqli_stmt_bind_param($stmt, "ss", $Email, $Password); // 执行查询 mysqli_stmt_execute($stmt); // 获取结果集 $result = mysqli_stmt_get_result($stmt); // 取出数据 if ($row = mysqli_fetch_assoc($result)) { $_SESSION['email'] = $row['email']; $_SESSION['roleid'] = $row['role_id']; header("Location: ../dashboard.php?login=success"); exit(); } else { header("Location: ../index.php?login=error"); exit(); }密码安全:不要明文存储
你的代码里直接比较明文密码,这是非常危险的做法。正确的流程是:- 用户注册时,用
password_hash($password, PASSWORD_DEFAULT)生成哈希值存入数据库 - 登录时,用
password_verify($Password, $row['password'])来验证密码是否匹配
- 用户注册时,用
修改后的完整示例代码
<?php session_start(); if(isset($_POST['submit'])) { include('CONFIG/config.php'); include('CONFIG/db.php'); $Email = trim($_POST['email']); $Password = trim($_POST['password']); // 错误处理:检查输入是否为空 if(empty($Email) || empty($Password)) { header("Location: ../index.php?login=empty"); exit(); } // 使用预处理语句查询用户和角色信息 $sql = "SELECT u.id, u.name, u.email, u.password, r.id as role_id FROM users u JOIN roles r ON u.role_id = r.id WHERE u.email = ?"; $stmt = mysqli_prepare($conn, $sql); mysqli_stmt_bind_param($stmt, "s", $Email); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); if ($row = mysqli_fetch_assoc($result)) { // 验证密码(假设数据库存的是哈希值) if(password_verify($Password, $row['password'])) { $_SESSION['email'] = $row['email']; $_SESSION['roleid'] = $row['role_id']; header("Location: ../dashboard.php?login=success"); exit(); } else { header("Location: ../index.php?login=wrongpwd"); exit(); } } else { header("Location: ../index.php?login=nouser"); exit(); } }else{ header("Location: ../index.php?login=error"); exit(); }
这样修改后,$_SESSION['roleid']就能正确存储你期望的数值(比如1)了,同时代码的安全性和效率也提升了不少。
内容的提问来源于stack exchange,提问作者Ken Verganio
相关产品推荐
相关产品推荐

