You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中orWhere关联查询异常:搜索Staff组返回Customer用户

问题:搜索指定用户组用户时返回了其他组的结果

我编写了一个Laravel控制器方法,用于通过姓名和邮箱搜索指定用户组(包含customer和staff组)的用户。但实际测试时,搜索staff组却返回了customer组的用户。

控制器代码

public function index(Request $request, UserGroup $group) { //group=staff
    $users = $group->users();

    if ($request->has('search') && $request->search) {
        $users->where('name', 'LIKE', '%' . $request->search . '%')
            ->orWhere(function ($builder) use ($request) {
                $builder->where('email', 'LIKE', '%' . $request->search . '%');
            });
    }

    return response()->json($users->get());
}

UserGroup模型关联代码

class UserGroup extends Model{

    //...
   
    public function users(): BelongsToMany | User | Collection
    {
        return $this->belongsToMany(User::class, 'user_user_group');
    }

   //...

}

错误原因

问题出在查询逻辑的优先级上:原代码中,关联查询的用户组过滤条件和搜索条件是平级的。当使用orWhere时,生成的SQL语句逻辑会变成:

SELECT * FROM users
INNER JOIN user_user_group ON users.id = user_user_group.user_id
WHERE user_user_group.user_group_id = ? 
AND name LIKE ? 
OR email LIKE ?

由于AND的优先级高于OR,实际执行逻辑是(组条件 AND 姓名匹配) OR 邮箱匹配——这就导致只要邮箱匹配的用户,不管属于哪个组都会被返回,完全绕过了用户组的限制。

修复方案

需要把姓名和邮箱的搜索条件包裹在同一个闭包里,让OR只作用于这两个条件,确保整体逻辑是组条件 AND (姓名匹配 OR 邮箱匹配)。

修正后的控制器代码

public function index(Request $request, UserGroup $group) { //group=staff
    $users = $group->users();

    if ($request->has('search') && $request->search) {
        $users->where(function ($builder) use ($request) {
            $builder->where('name', 'LIKE', '%' . $request->search . '%')
                ->orWhere('email', 'LIKE', '%' . $request->search . '%');
        });
    }

    return response()->json($users->get());
}

额外优化:避免SQL注入

直接拼接%和搜索关键词存在SQL注入风险,建议使用参数绑定的方式:

$users->where(function ($builder) use ($request) {
    $searchTerm = "%{$request->search}%";
    $builder->where('name', 'LIKE', $searchTerm)
        ->orWhere('email', 'LIKE', $searchTerm);
});
// 或者Laravel 9+可以用whereLike简化:
$users->where(function ($builder) use ($request) {
    $builder->whereLike('name', "%{$request->search}%")
        ->orWhereLike('email', "%{$request->search}%");
});

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:40:30