【问题标题】:Laravel where clause not working after series of orwhereLaravel where 子句在一系列 orwhere 之后不起作用
【发布时间】:2018-03-08 07:50:18
【问题描述】:

我有一个基于某些参数获取用户的查询。

$users = User::where(function($query) use($queryTags_userIDs) {
    $query->whereIn('id', $queryTags_userIDs);
})->orWhere(function($query) use($queryImageTitles_userIDs) {
    $query->whereIn('id', $queryImageTitles_userIDs);
})->orWhere('username', 'LIKE', "%{$query}%")
    ->orWhere('keywords', 'LIKE', "%{$query}%")     
    ->orWhere('profile_text', 'LIKE', "%{$query}%")
    ->orWhere('tagline', 'LIKE', "%{$query}%")
    ->where('role', 2)
    ->orderBy('last_login', 'desc')
    ->paginate(15);

现在,这一切都很好。

除了这部分:

->where('role', 2)

它不是获取角色为 2 的用户,而是获取每个角色的用户。

但是,如果我去掉一些 orWheres,它会起作用。

如果我摆脱这 3 个 orWheres:

->orWhere('keywords', 'LIKE', "%{$query}%")     
->orWhere('profile_text', 'LIKE', "%{$query}%")
->orWhere('tagline', 'LIKE', "%{$query}%")

然后它开始仅获取角色 2 的用户。事实上,无论出于何种原因,这 3 个特定的 orWhere 都会导致问题

如果我将查询减少到只有

$users = User::where('username', 'LIKE', "%{$query}%")
    ->orWhere('keywords', 'LIKE', "%{$query}%")     
    ->where('role', 2)
    ->orderBy('last_login', 'desc')
    ->paginate(7);

它仍然从角色 2 之外获取用户。

但是,如果要切换到这个:

$users = User::where('username', 'LIKE', "%{$query}%")
    ->where('role', 2)
    ->orderBy('last_login', 'desc')
    ->paginate(7);

然后突然之间它只从角色 2 获取用户。

为什么会这样?我觉得我错过了一些非常明显的东西,因为这没有任何意义。

编辑

为了回应 Bassem El Hachem,我将 role = 2 放在查询的开头。但它仍然不起作用。这是更改后的查询:

"select * from users where role = ? and (id in (?, ?, ?, ?, ?, ?, ?)) 或 (id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) 或 (username LIKE ? 或 keywords LIKE ? 或 profile_text 喜欢?或tagline LIKE ?) 订购last_login desc"

【问题讨论】:

  • 试试我的新答案。其他的WHERE 都是ORs 还是有另外一个强制的WHERE?
  • 新答案有效。

标签: php mysql sql laravel


【解决方案1】:

那是因为你在 SQL 中的查询是这样的:

WHERE keywords like '%...%' OR profile_text LIKE '%...%' 
OR tagline LIKE '%...%' AND role=2

SQL 中的AND 运算符类似于乘法,它添加了一个括号,这意味着您的查询实际上是:

WHERE keywords like '%...%' OR profile_text LIKE '%...%' 
OR (tagline LIKE '%...%' AND role=2)

因此,过滤器role=2 仅应用于特定行tagline LIKE '%...%' 所在的行)。对于keywords like '%...%' OR profile_text LIKE '%...%' 所在的行,role 可以是任何值,这不是您想要的。

您需要做的是直接在user 上对role 应用过滤WHERE。这无疑也有助于提高效率。

$users = User::where('role', 2)
  ->where(function($q) use($queryTags_userIDs,$queryImageTitles_userIDs,$query) {
      $q->whereIn('id', $queryTags_userIDs)
      ->orWhereIn('id', $queryImageTitles_userIDs)
      ->orWhere('username', 'LIKE', "%{$query}%")
      ->orWhere('keywords', 'LIKE', "%{$query}%")     
      ->orWhere('profile_text', 'LIKE', "%{$query}%")
      ->orWhere('tagline', 'LIKE', "%{$query}%");
   })->orderBy('last_login', 'desc')
   ->paginate(15);

由于不清楚您想要什么结果,我建议以 SQL 语法查看查询。这可以通过将paginate(15) 替换为toSql()dd() 结果来完成。

【讨论】:

    猜你喜欢
    • 2019-06-15
    • 2020-05-08
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 2019-11-05
    • 1970-01-01
    • 2017-07-22
    相关资源
    最近更新 更多