
本文讲解如何通过 left join 与 is null 条件,高效、安全地查询未被当前用户关注的用户列表,避免手动拼接 in 子句带来的 sql 注入风险和性能问题。
本文讲解如何通过 left join 与 is null 条件,高效、安全地查询未被当前用户关注的用户列表,避免手动拼接 in 子句带来的 sql 注入风险和性能问题。
在开发社交类应用(如关注/粉丝系统)时,一个常见需求是:获取当前用户尚未关注的随机用户列表。许多开发者会本能地分两步实现——先查出已关注的 ID 列表,再用 NOT IN (...) 排除这些 ID。但这种做法存在严重隐患:
- ❌ 手动拼接 implode("', '", $ids) 极易引发 SQL 注入(尤其当 $ids 来源不可信时);
- ❌ 若 $followers 为空数组,NOT IN ('') 会导致语法错误或逻辑失效;
- ❌ 多次查询 + PHP 层数据处理,降低数据库执行效率。
✅ 更优解是:单条 SQL 利用 LEFT JOIN + IS NULL 语义,直接筛选“在 usersdb 中存在、但在 followerstable 中无匹配记录”的用户。
以下为推荐写法(含参数化绑定,安全可靠):
// 假设 $currentUserId 是当前登录用户的 ID(需提前验证为整型)
$currentUserId = (int)$_SESSION['user_id'];
// 查询所有未被当前用户关注的用户(排除自己)
$stmt = $conne->prepare("
SELECT r.*
FROM usersdb r
LEFT JOIN followerstable p
ON r.ids = p.thisuser AND p.ids = :current_id
WHERE p.thisuser IS NULL
AND r.ids != :current_id
ORDER BY RAND()
LIMIT 3
");
$stmt->bindValue(':current_id', $currentUserId, PDO::PARAM_INT);
$stmt->execute();
$recommendUsers = $stmt->fetchAll(PDO::FETCH_ASSOC);
? 关键说明:
- LEFT JOIN ... ON r.ids = p.thisuser AND p.ids = :current_id 精确关联「目标用户 ID」与「当前用户作为关注者(followerstable.ids)」的关系;
- WHERE p.thisuser IS NULL 表示该用户在 followerstable 中没有以当前用户为关注者的记录,即“未被关注”;
- AND r.ids != :current_id 避免返回用户自身(逻辑健壮性);
- 全程使用 bindValue() 参数化绑定,杜绝 SQL 注入;
- 数据库原生完成过滤,无需 PHP 层遍历或字符串拼接,性能更优。
⚠️ 注意事项:
- 确保 followerstable.ids 和 followerstable.thisuser 字段有适当索引(如联合索引 (ids, thisuser)),否则 LEFT JOIN 可能变慢;
- ORDER BY RAND() 在大数据量下性能较差,生产环境建议改用主键范围随机采样等优化方案;
- 若需支持“关注关系双向独立”(如互相关注),请根据实际表结构调整 JOIN 条件。
此方案简洁、安全、高效,是 PDO 场景下处理“NOT IN 关联集合”问题的标准实践。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











