如何修改PHP查询,实现仅匹配全部$_GET['skills']参数的过滤?
实现匹配所有传入技能的过滤查询修改
当前代码通过IN子查询实现的是匹配任意传入技能的用户,要改成仅显示匹配所有传入技能的用户,需要通过分组统计匹配技能数量的方式调整逻辑,具体修改如下:
修改后的代码
if(isset($_GET['skills']) && !empty($_GET['skills'])) { $skillIds = $_GET['skills']; $skillCount = count($skillIds); $skillTable = memberSkillModel::factory()->getTable(); $memberModel->where("t1.id IN( SELECT TMS.member_id FROM `{$skillTable}` AS `TMS` WHERE `TMS`.skill_id IN(".join(",", $skillIds).") GROUP BY TMS.member_id HAVING COUNT(DISTINCT TMS.skill_id) = {$skillCount} )"); }
核心逻辑说明
- 分组统计:通过
GROUP BY TMS.member_id对用户的技能记录分组,统计每个用户匹配的技能数量 - 数量校验:
HAVING COUNT(DISTINCT TMS.skill_id) = {$skillCount}确保用户匹配到的技能数量和传入的技能总数一致,只有满足这个条件的用户才拥有所有传入的技能 - 去重计数:使用
COUNT(DISTINCT)是为了避免同一用户同一技能被重复记录的情况(如果技能关联表存在重复数据)
安全优化建议
原代码直接将$_GET参数拼接进SQL,存在SQL注入风险,建议使用参数绑定的方式优化(如果你的ORM支持参数绑定):
if(isset($_GET['skills']) && !empty($_GET['skills'])) { $skillIds = $_GET['skills']; $skillCount = count($skillIds); $skillTable = memberSkillModel::factory()->getTable(); // 生成对应数量的占位符 $placeholders = implode(',', array_fill(0, $skillCount, '?')); $memberModel->where("t1.id IN( SELECT TMS.member_id FROM `{$skillTable}` AS `TMS` WHERE `TMS`.skill_id IN({$placeholders}) GROUP BY TMS.member_id HAVING COUNT(DISTINCT TMS.skill_id) = ? )", array_merge($skillIds, [$skillCount])); }
内容的提问来源于stack exchange,提问作者Betty
相关产品推荐
相关产品推荐

