Laravel查询已限制角色为教师,搜索时仍返回超管用户是什么原因?
问题原因
这是SQL逻辑运算符优先级导致的查询条件逻辑错误。
Laravel Eloquent会按书写顺序直接拼接查询条件,你当前写法生成的原生SQL逻辑等价于:
WHERE status = 'active' AND role.name = 'teacher' AND name like '%xxx%' AND first_name like '%xxx%' OR last_name like '%xxx%' OR description like '%xxx%' -- 其余所有orWhere/OrWhereRelation条件
SQL中AND的执行优先级高于OR,所以只要后面任意一个OR条件匹配成功,整个WHERE判断结果就为真,直接绕过了前面的「活跃状态、角色为教师」的限定条件,所以会返回匹配到搜索关键词的超级管理员用户。
修复方案
把所有搜索相关的条件封装到同一个闭包where中做逻辑分组,修正后的代码如下:
$data['tutors'] = User::where('status', 'active') ->whereRelation('role','name', 'teacher') ->where(function ($query) use ($req) { // 所有搜索条件都放在这个闭包里,作为一组OR判断 $query->where('name', 'like', "%{$req}%") ->orWhere('first_name', 'like', "%{$req}%") ->orWhere('last_name', 'like', "%{$req}%") ->orWhere('description', 'like', "%{$req}%") ->orWhereRelation('country','name', 'like', "%{$req}%") ->orWhereRelation('state','name', 'like', "%{$req}%") ->orWhereRelation('city','name', 'like', "%{$req}%") ->orWhereRelation('languages.language','name', 'like', "%{$req}%") ->orWhereRelation('gigs','title', 'like', "%{$req}%") ->orWhereRelation('gigs','price', 'like', "%{$req}%") ->orWhereRelation('gigs','description', 'like', "%{$req}%") ->orWhereRelation('skills.skill','name', 'like', "%{$req}%"); }) ->with(['languages.language', 'skills.skill', 'country']) ->paginate(5);
修改后生成的SQL逻辑会变成:
WHERE status = 'active' AND role.name = 'teacher' AND ( name like '%xxx%' OR first_name like '%xxx%' OR last_name like '%xxx%' -- 其余所有搜索条件 )
这样就强制要求所有查询必须先满足「活跃用户、角色为教师」的基础限定,再判断是否匹配任意一个搜索条件,不会再出现不符合角色要求的用户被返回的问题。
内容的提问来源于stack exchange,提问作者Rehab Zafar
相关产品推荐
相关产品推荐

