Laravel where子句在一系列orwhere之后无效

时间:2017-09-26 23:55:19

标签: php mysql sql laravel

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

$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的位置,它会获取每个角色的用户。

然而,如果我摆脱某些或者某些方面它会起作用。

如果我摆脱这些3或者球:

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

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

如果我将查询简化为

$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。但它仍然无法奏效。这是更改后的查询:

  

"从users中选择* role =?和(id in(?,?,?,?,?,   ?,?))或(id in(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,   ?,?,?,?))或(username LIKE?或keywords LIKE?或   profile_text喜欢?或tagline LIKE?)按last_login desc"

排序

1 个答案:

答案 0 :(得分: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上的过滤WHERE直接应用于user。这无疑也有助于提高效率。

$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()结果来完成。