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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:52:53