仅可访问Moodle数据库及表,如何结合role id与user id用MySQL查用户当前角色
问题说明
- 仅拥有Moodle数据库及数据表访问权限,需要结合role id、user id两个字段查询用户当前持有的所有角色
- 现有自写代码仅能展示最新一次的角色分配结果,无法返回全部角色
- 附原始问题代码:
//Get user id $rowSQL = "SELECT id FROM mdl_user WHERE username=?"; $stmt = $linkMDL->prepare($rowSQL); $stmt->bind_param('s', $username); $stmt->execute(); $userid = $stmt->get_result(); $userid = $userid->fetch_row(); $userid = $userid[0]; echo json_encode($userid); $stmt->close; //Check user role in Moodle by user id $rowSQL = "SELECT roleid FROM mdl_role_assignments WHERE timemodified = (SELECT MAX(timemodified) FROM mdl_role_assignments WHERE userid=?)"; $stmt = $linkMDL->prepare($rowSQL); $stmt->bind_param('s', $userid); $stmt->execute(); $roleid = $stmt->get_result(); $roleid = $stmt->fetch_row(); $roleid = $roleid[0]; echo json_encode($roleid); $stmt->close;
现有代码的核心问题
- 角色查询逻辑偏差:原SQL通过匹配最大修改时间定位单条角色记录,仅会返回时间最新的1个roleid,完全无法覆盖用户持有的全部角色
- 存在语法错误:mysqli预处理对象的close方法必须带括号调用,原代码写的
$stmt->close漏了括号,运行时会触发语法报错 - 取值逻辑不全:原代码只调用一次fetch_row取单条结果,即使SQL返回多条角色记录,也只能拿到第一条数据
修正后的可运行代码
// 根据用户名查询对应用户ID $rowSQL = "SELECT id FROM mdl_user WHERE username = ? LIMIT 1"; $stmt = $linkMDL->prepare($rowSQL); $stmt->bind_param('s', $username); $stmt->execute(); $userQueryRes = $stmt->get_result(); $userRow = $userQueryRes->fetch_row(); // 兼容用户名不存在的场景,避免空值访问报错 $userid = $userRow ? $userRow[0] : 0; $stmt->close(); // 查询对应用户持有的全部不重复角色ID $roleSQL = "SELECT DISTINCT roleid FROM mdl_role_assignments WHERE userid = ?"; $stmt = $linkMDL->prepare($roleSQL); // userid为整型值,绑定参数类型改为i更匹配字段类型 $stmt->bind_param('i', $userid); $stmt->execute(); $roleQueryRes = $stmt->get_result(); // 遍历所有查询结果,收集全部角色ID $allUserRoles = []; while ($roleRow = $roleQueryRes->fetch_assoc()) { $allUserRoles[] = $roleRow['roleid']; } $stmt->close(); // 统一输出用户ID和关联的全部角色ID echo json_encode([ 'userid' => $userid, 'all_roleids' => $allUserRoles ]);
关键调整说明
- 移除了原SQL中取最大修改时间的限制条件,直接按userid匹配所有关联的角色分配记录,配合
DISTINCT去重,避免同一角色重复分配导致的冗余返回 - 修正了close方法漏写括号的语法问题,将userid的绑定参数类型从字符串
s改为整型i,匹配Moodle表中userid字段的存储类型 - 用循环遍历替代单次取单条结果的逻辑,把查询返回的所有roleid都存入数组,实现“返回用户当前持有全部角色”的需求
- 进阶优化:如果需要排除已失效的历史角色分配记录,可在角色查询的WHERE条件中增加时间范围判断,筛选
timestart <= 当前时间且(timeend = 0 OR timeend > 当前时间)的记录,过滤掉已过期、未生效的角色分配数据
内容的提问来源于stack exchange,提问作者user14337693
相关产品推荐
相关产品推荐

