Laravel中setBindings结合LIKE语句无结果问题排查
问题分析与解决办法
首先给你吃个定心丸:你最开始的写法其实已经是安全的,完全不用担心SQL注入风险!Laravel的查询构建器会自动把你拼接的%'.$keywords.'%作为参数绑定到SQL语句中,而不是直接把变量拼进SQL里,所以注入问题根本不存在。
那为什么用setBindings的写法会返回零结果呢?原因很简单:你在where条件里写的%?%,这个?并没有被Laravel识别为参数占位符——它只是字符串里的一个普通字符而已。最终执行的SQL会变成:
SELECT page_translations.id FROM page_translations WHERE page_translations.title LIKE '%?%'
这里的?就是字面量,而不是你绑定的'e',自然找不到匹配的记录。
正确的参数绑定写法
如果你想手动用参数绑定的方式实现(其实没必要,但可以了解),应该把%和变量结合后作为绑定值,而不是把?放在%中间。有几种可行方式:
方式1:直接把%加到绑定变量中(和你最初的写法本质一致,更清晰)
$keywords = 'e'; $searchTerm = "%{$keywords}%"; $pages = DB::table('page_translations') ->select('page_translations.id') ->where('page_translations.title', 'LIKE', $searchTerm) ->get() ->toArray();
这种写法和你最开始的代码效果完全一样,而且同样安全。
方式2:使用setBindings的正确姿势
一定要用setBindings的话,得让占位符是独立的,再把包含%的字符串作为绑定值:
$keywords = 'e'; $pages = DB::table('page_translations') ->select('page_translations.id') ->where('page_translations.title', 'LIKE', '?') // 这里的?是独立的占位符 ->setBindings(["%{$keywords}%"]) ->get() ->toArray();
更常用的是直接在whereRaw里传递绑定数组:
$keywords = 'e'; $pages = DB::table('page_translations') ->select('page_translations.id') ->whereRaw('page_translations.title LIKE ?', ["%{$keywords}%"]) ->get() ->toArray();
方式3:用Laravel自带的whereLike(Laravel 9及以上版本支持)
Laravel 9+提供了更简洁的whereLike方法,自动帮你处理LIKE查询的通配符:
$keywords = 'e'; $pages = DB::table('page_translations') ->select('page_translations.id') ->whereLike('page_translations.title', $keywords) ->get() ->toArray();
默认会给关键词两边加上%,如果需要自定义通配符位置,还能传第三个参数,比如->whereLike('title', $keywords, 'before')只会在前面加%。
总结
- 你最初的写法已经安全,不需要额外用
setBindings; - 用
setBindings失效的核心原因是%?%里的?不是有效的占位符; - 推荐用最初的写法或者
whereLike(版本支持的话),简洁又安全。
内容的提问来源于stack exchange,提问作者learningtech
相关产品推荐
相关产品推荐

