首页 > 解决方案 > Laravel 复杂的地方和地点

问题描述

我有一个查询,可以让所有用户在 html 复选框数组上选择一些特定技能,这些值是技能数据库中的 ID。

例如,当您具有 Laravel 和 SQL 技能时,搜索查询应仅在用户输入 laravel 和 sql 或其中之一时返回您,否则不应显示您。

现在发生的是另一种方式:当您选择 laravel OR sql 时,它会在用户列表中显示您,但如果您同时选择两者,您将不会,但您仍然拥有这些技能。如果我将 where 替换为 orWhere,它会正常运行,但即使我们输入了您没有的其他技能,也会将您显示为相关用户。

这是我的查询的一部分:

->when(isset($data['skills']) and $data['skills'] != null, function ($query) use ($data){
                $query->whereHas('skills', function ($subQuery) use ($data) {
                    for($i = 0; $i < count($data['skills']); $i++){
                            $subQuery->where('skills.id', $data['skills'][$i]);
                    }
                });
            })

for 只是为了打开前面传来的技能数组。

任何帮助都会很有用。谢谢

标签: laravel

解决方案


这里的问题有点微妙:

下面是 whereHas 相关查询的样子:

select * from skills
where (skills.foreign_id = related_table.id 
       or `id` = ? or `id` = ? ... -- This is the orWhere part
);

正如您所看到的,对于与该关系 ID或那些技能相对应的所有内容(即使它们不属于该人),or 始终为真,因此基本上属于该人的所有内容加上最终将获得的更多行过滤。

你应该做的是:

 ->when(isset($data['skills']) and $data['skills'] != null, function ($query) use ($data){
            $query->whereHas('skills', function ($subQuery) use ($data) {
                $subQuery->where(function ($subSubQuery) use ($data) {
                    for($i = 0; $i < count($data['skills']); $i++){
                            $subSubQuery->orWhere('skills.id', $data['skills'][$i]);
                    }
                });
            });
        })

这将产生一个如下所示的关系查询:

select * from skills 
where skills.foreign_id = related_table.id 
      and (`id` = ? or `id` = ?) -- orWhere is now wrapped in parentheses

你当然可以总是这样做:

->when(isset($data['skills']) and $data['skills'] != null, function ($query) use ($data){
   $query->whereHas('skills', function ($subQuery) use ($data) {
          $subQuery->whereIn('skills.id', $data['skills']);
    });
})

推荐阅读