
本文详解 laravel eloquent 和 query builder 中安全、兼容地查询 mysql/postgresql 等数据库 json 列(如 `info->id`)的最佳实践,纠正 `whereraw` 拼接导致的 sql 注入与语法错误,并介绍 `wherejsoncontains`、`wherejsonlength` 等高级 json 查询方法。
在 Laravel 中对 JSON 类型字段(如 MySQL 的 JSON 列或 PostgreSQL 的 jsonb)进行条件查询时,切勿直接拼接变量到 whereRaw 中——这不仅存在严重的 SQL 注入风险,还会因引号缺失或类型隐式转换导致报错(例如你遇到的 Unknown column '6112' 错误)。该错误本质是 MySQL 将未加引号的数字 6112 误解析为列名而非字面值,根源在于 ->whereRaw('JSON_EXTRACT(info, "$.id") = '.$value) 缺少参数绑定和字符串转义。
✅ 正确且推荐的方式是使用 Laravel 原生支持的 JSON 路径操作符 ->:
$order = DB::table('orders')
->where('info->id', $value) // ✅ 自动处理类型与转义,等价于 JSON_EXTRACT(info, '$.id')
->first();该语法在 Laravel 5.6+ 中原生支持,底层会根据数据库类型自动编译为对应函数:
- MySQL → JSON_EXTRACT("info", "$.id") = ?
- PostgreSQL → "info"->>'id' = ?
- SQLite(启用 JSON1)→ json_extract("info", '$.id') = ?
同时,它会通过 PDO 参数绑定安全传递 $value,彻底规避注入与语法错误。
? 进阶 JSON 查询场景(仅限 MySQL/PostgreSQL):
-
匹配 JSON 数组中是否包含某值(如 info->tags 是 ["urgent", "paid"]):
$orders = DB::table('orders') ->whereJsonContains('info->tags', 'urgent') ->get(); -
匹配多个值(AND 逻辑):
// 查找同时包含 'urgent' 和 'paid' 的订单 $orders = DB::table('orders') ->whereJsonContains('info->tags', ['urgent', 'paid']) ->get(); -
按 JSON 数组长度筛选:
// 查找 tags 数组长度大于 1 的订单 $orders = DB::table('orders') ->whereJsonLength('info->tags', '>', 1) ->get();
⚠️ 注意事项:
- whereJsonContains 和 whereJsonLength 不支持 SQLite(除非手动启用并验证 JSON1 扩展);
- JSON 路径区分大小写(如 'info->Id' ≠ 'info->id');
- 若 JSON 字段可能为 NULL,建议补充空值判断:->whereNotNull('info')->where('info->id', $value);
- 在 Eloquent 模型中,可直接复用相同语法:
$order = Order::where('info->id', $value)->first();
总结:始终优先使用 -> 操作符替代手写 JSON_EXTRACT + whereRaw;它更简洁、安全、跨库兼容,且由 Laravel 框架统一维护底层适配逻辑。









