Laravel Eloquent多Where与OrWhere查询失效问题排查
解决多租户应用中搜索功能的租户隔离问题
我之前踩过一模一样的坑!你这个问题核心就是OR条件的括号范围没处理对,导致租户的company_id和subcompany_id过滤逻辑被OR给“绕开”了,直接返回了所有符合搜索条件的数据,完全没做租户隔离。
问题根源拆解
你的需求是:必须同时满足「用户所属租户(company_id + subcompany_id)」AND「用户的搜索条件(多列宽泛搜/单列指定搜)」。但如果把搜索的OR条件和租户条件平级写,生成的SQL逻辑会变成:
WHERE company_id = ? AND subcompany_id = ? OR column1 LIKE ? OR column2 LIKE ?
这在逻辑上等价于「(租户条件)OR(搜索条件)」,自然会返回所有符合搜索条件的结果,不管租户归属。
正确的写法示例(以Eloquent为例)
要把所有搜索相关的OR条件包裹在一个子where闭包里,让它和租户条件形成严格的AND关系:
1. 多列宽泛搜索场景
// 先锁定租户范围,再把搜索的OR条件包在子where里 $query->where('company_id', $user->company_id) ->where('subcompany_id', $user->subcompany_id) ->where(function ($searchQuery) use ($keyword) { // 这里放所有需要宽泛搜索的列 $searchQuery->orWhere('column1', 'like', "%{$keyword}%") ->orWhere('column2', 'like', "%{$keyword}%") ->orWhere('column3', 'like', "%{$keyword}%"); });
生成的SQL会是:
WHERE company_id = ? AND subcompany_id = ? AND (column1 LIKE ? OR column2 LIKE ? OR column3 LIKE ?)
这样就保证了必须先满足租户条件,再匹配搜索条件。
2. 支持单列指定搜索的场景
如果用户可以选择单列搜索,只需要在子闭包里做个判断即可:
$query->where('company_id', $user->company_id) ->where('subcompany_id', $user->subcompany_id) ->where(function ($searchQuery) use ($keyword, $selectedColumn) { if ($selectedColumn) { // 用户指定了单列,直接精准搜索该列 $searchQuery->where($selectedColumn, 'like', "%{$keyword}%"); } else { // 用户没指定,多列宽泛搜索 $searchQuery->orWhere('column1', 'like', "%{$keyword}%") ->orWhere('column2', 'like', "%{$keyword}%") ->orWhere('column3', 'like', "%{$keyword}%"); } });
关键总结
多租户的核心隔离条件(company_id、subcompany_id)必须作为顶级的AND条件,所有搜索相关的OR逻辑都要嵌套在子查询里,这样才能避免OR条件破坏租户隔离的规则。
内容的提问来源于stack exchange,提问作者ahinkle
相关产品推荐
相关产品推荐

