
在 laravel 中使用原生 sql 的命名占位符(如 `:id`)无法直接绑定数组值,必须改用查询构建器的 `wherein()` 方法或动态生成占位符,否则会导致查询结果异常。
当需要基于多个 ID 执行 WHERE IN 查询时,切勿将数组 implode() 成字符串后传入命名绑定参数(如 :id),因为 PDO 不支持将单个占位符展开为多个值。你遇到“只返回一条结果”的问题,正是因为 :id 被当作一个整体字符串(如 '6,7,8,9')参与比较,而数据库实际执行的是类似 id IN ('6,7,8,9') 的语义——这等价于匹配一个字符串字面量,而非四个整型 ID,因此极大概率仅匹配到 ID 值恰好等于该字符串的某条记录(通常无匹配,或因隐式类型转换产生意外结果)。
✅ 推荐方案:使用 Query Builder(最安全、简洁、可读性强)
Laravel 查询构建器原生支持数组绑定,自动处理占位符数量与类型:
$id = [6, 7, 8, 9];
$result = DB::table('failed_jobs')
->where('connection', 'redis')
->whereIn('id', $id)
->get();该写法会自动生成形如 WHERE connection = ? AND id IN (?, ?, ?, ?) 的预处理语句,并安全绑定四个独立参数,完全规避 SQL 注入与类型错误风险。
⚠️ 若必须使用原生 SQL(不推荐,仅作了解):需动态生成对应数量的占位符:
$id = [6, 7, 8, 9];
$placeholders = str_repeat('?,', count($id) - 1) . '?';
$params = array_merge(['redis'], $id); // connection 在前,id 值在后
$result = DB::select(
"SELECT * FROM failed_jobs WHERE connection = ? AND id IN ($placeholders)",
$params
);? 注意:此处必须用 ? 位置占位符(非 :name),且 $params 顺序需严格对应占位符出现顺序;whereIn() 内部正是这样实现的——无需手动拼接。
? 总结:
- 永远避免对 IN 子句使用单个命名绑定(如 :ids);
- 优先选用 whereIn() 等查询构建器方法,语义清晰、类型安全、兼容所有数据库驱动;
- 原生 SQL 动态占位符方式易出错,仅在特殊场景(如复杂联合查询无法用 Builder 表达)下谨慎使用;
- 所有用户输入务必通过参数绑定传递,杜绝字符串拼接 SQL。










