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

Laravel Query Builder参数映射错误原因及修复方法咨询

错误成因
  • 参数绑定顺序完全错位:Laravel查询构建器是按参数添加的先后顺序来匹配SQL占位符的。你用DB::raw硬写了billable_type = 'App\Models\Citation',直接打乱了withSum的自动绑定逻辑——withSum原本会给多态关联的billable_type生成占位符并绑定正确值,但硬编码的字符串抢占了参数位置,导致后续的日期参数被错误塞到了withSum的占位符里,同时withSum的类型值又跑到了日期条件的位置,造成两处参数完全错位。
  • 破坏多态关联的自动处理规则:settlements属于多态关联,withSum会自动从Citation模型的关联定义里读取billable_type的值,根本不需要手动硬编码。你在DB::raw里写死类型字符串,直接破坏了框架的参数绑定流程,引发连锁错误。
修复方案

替换硬编码子查询,用查询构建器规范实现

把原来的DB::raw子查询改成Laravel原生查询构建器语法,让框架自动处理参数绑定,避免顺序混乱:

// 先构建支付统计的子查询
$paymentsSubquery = Settlement::query()
    ->select('billable_id')
    ->selectRaw('sum(amount_dollars) as amount_paid')
    ->where('billable_type', Citation::class) // 用类常量替代硬编码,框架自动绑定参数
    ->whereNull('deleted_at')
    ->groupBy('billable_id');

// 主查询重构
Citation::with([
    'person:id,name_first,name_last',
    'employer:id,name',
    'incident',
])
->withSum('settlements', 'amount_dollars')
->leftJoinSub($paymentsSubquery, 'payments', function (JoinClause $join) {
    $join->on('payments.billable_id', '=', 'citations.id')
        ->whereColumn(
            DB::raw('`citations`.`amount_dollars` - `citations`.`amount_discount_dollars`'),
            '>',
            'amount_paid'
        );
})
->whereDate('created_at', '>=', '2017-10-16')
->whereDate('created_at', '<=', now()) // 用now()动态获取当前日期,避免写死
->get();

关键修复点说明

  1. 用leftJoinSub替代leftJoin+DB::raw,让子查询的参数绑定完全由框架接管,避免手动硬编码干扰全局参数顺序。
  2. 用Citation::class替代硬编码的类名字符串,既保证类型值准确,又让框架自动处理参数绑定,避免占位符错位。
  3. 用whereDate替代直接where,明确针对日期部分查询,同时用now()动态获取当前日期,提升代码灵活性。

内容的提问来源于stack exchange,提问作者Jay Bienvenu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:25:56