Laravel Query Builder生成SQL异常:变量未替换为字符串值
Laravel Query Builder toSql() 返回占位符而非实际值的原因
我编写了一段Laravel查询代码,定义了字符串变量$abort(值为"Aborted")和$pend(值为"Pending"),使用Query Builder构建查询后调用toSql()方法,返回的SQL语句中这两个变量并未被替换为实际字符串,而是显示为占位符?。相关代码及返回SQL如下:
代码示例
$abort = "Aborted"; $pend = "Pending"; $transactions = DB::table('callpay_transactions') ->select(DB::raw('SUBSTR(created,1,7) as YrMth'), DB::raw('SUM(amount) as total_sales')) ->where('status', '!=', $abort) ->where('status', '!=', $pend) ->groupBy(DB::raw('SUBSTR(created,1,7)')) ->toSql(); dd($transactions);
返回的SQL
select SUBSTR(created,1,7) as YrMth, SUM(amount) as total_sales from `callpay_transactions` where `status` != ? and `status` != ? group by SUBSTR(created,1,7)
原因说明
这是Laravel Query Builder的预编译SQL机制导致的,核心目的有两个:
- 防止SQL注入:通过参数绑定的方式,避免用户输入直接拼接到SQL中引发注入风险
- 提升查询性能:数据库可以缓存预编译的SQL模板,后续执行相同结构的查询时无需重新解析
toSql()方法的设计就是只返回未绑定参数的SQL模板,不会将占位符替换为实际参数值。
查看带实际参数的完整SQL(调试用)
如果需要看到替换后的完整SQL,可以用以下两种方式:
方式1:监听查询事件
DB::listen(function ($query) { dump('SQL语句:' . $query->sql); dump('绑定参数:' . print_r($query->bindings, true)); }); // 执行查询(注意这里调用get()而非toSql()) $transactions = DB::table('callpay_transactions') ->select(DB::raw('SUBSTR(created,1,7) as YrMth'), DB::raw('SUM(amount) as total_sales')) ->where('status', '!=', $abort) ->where('status', '!=', $pend) ->groupBy(DB::raw('SUBSTR(created,1,7)')) ->get();
方式2:手动替换占位符(仅调试用)
$builder = DB::table('callpay_transactions') ->select(DB::raw('SUBSTR(created,1,7) as YrMth'), DB::raw('SUM(amount) as total_sales')) ->where('status', '!=', $abort) ->where('status', '!=', $pend) ->groupBy(DB::raw('SUBSTR(created,1,7)')); $sql = $builder->toSql(); $bindings = $builder->getBindings(); foreach ($bindings as $binding) { // 处理不同类型的参数 $value = match(true) { is_string($binding) => "'" . addslashes($binding) . "'", is_null($binding) => 'NULL', default => $binding }; $sql = preg_replace('/\?/', $value, $sql, 1); } dd($sql);
内容的提问来源于stack exchange,提问作者The Mac
相关产品推荐
相关产品推荐

