You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:55:20