
在 laravel 中使用原生 sql 的命名占位符(如 `:id`)无法直接绑定数组值,必须改用查询构建器的 `wherein()` 方法或动态生成占位符,否则会导致查询结果不全。
在 Laravel 开发中,当需要根据一组 ID(如 [6, 7, 8, 9])查询数据库记录时,开发者有时会尝试在原生 SQL 中使用命名绑定(DB::select() + :id),但这种方式存在根本性限制:PDO 不支持将数组直接绑定为单个命名参数。你提供的代码:
$id = [6, 7, 8, 9];
$params = [
'connection' => 'redis',
'id' => implode(',', $id) // ❌ 错误:这会把整个字符串 '6,7,8,9' 当作一个值
];
$result = DB::select(DB::raw("
SELECT * FROM failed_jobs
WHERE id IN (:id) AND connection = :connection
"), $params);实际执行的 SQL 等价于:
WHERE id IN ('6,7,8,9') -- ⚠️ 单引号包裹 → 被视为一个字符串字面量,非四个独立整数因此仅匹配 id = 6(若该行恰好 id 字段值为字符串 '6,7,8,9')或完全无匹配,导致结果数量异常。
✅ 推荐方案:使用 Query Builder 的 whereIn()(最安全、简洁、可读性强)
$id = [6, 7, 8, 9];
$result = DB::table('failed_jobs')
->where('connection', 'redis')
->whereIn('id', $id) // ✅ Laravel 自动处理参数绑定与占位符扩展
->get();底层生成的 SQL 类似:
SELECT * FROM `failed_jobs` WHERE `connection` = ? AND `id` IN (?, ?, ?, ?) -- 绑定参数:['redis', 6, 7, 8, 9]
完全避免 SQL 注入风险,并兼容所有数据库驱动。
⚠️ 补充说明:若必须使用原生 SQL(极少数场景)
需手动构造等量占位符,并逐个绑定:
$id = [6, 7, 8, 9];
$placeholders = str_repeat('?,', count($id) - 1) . '?';
$params = array_merge(['redis'], $id);
$result = DB::select(
"SELECT * FROM failed_jobs WHERE id IN ($placeholders) AND connection = ?",
$params
);但此方式易出错、可维护性差,强烈不建议在常规业务中使用。
? 总结
- ❌ :param 命名绑定不支持数组展开;implode() 后绑定是常见误区;
- ✅ 优先使用 whereIn() —— 它是 Laravel 专为该场景设计的安全抽象;
- ? 所有参数均经 PDO 预处理绑定,杜绝 SQL 注入;
- ? 性能无损耗,且支持链式调用、分页、关系预加载等高级特性。










