Laravel如何仅加载中间表pivot额外字段而不加载关联模型
最优解法:直接通过关联查询构造器在数据库层面求和
你只需要把调用关联的方式从「属性调用」改成「方法调用」即可,不需要实例化任何关联的Charge模型,直接在SQL层面完成聚合计算:
$payment = Payment::find(/* 你的payment id */); // 注意charges后面加了(),返回的是关联查询构造器,不是模型集合 $paid_amount = $payment->charges()->sum('charge_payment.amount');
原理说明
- 不带
()调用$payment->charges时,Laravel会先查询所有关联的Charge记录、实例化模型,再返回集合,你之后调用的sum是PHP集合层面的计算,会浪费内存和查询IO。 - 带
()调用$payment->charges()时,返回的是BelongsToMany查询构造器,直接调用sum方法会生成对应的SUM聚合SQL,仅返回计算后的数值,不会加载任何关联模型,性能提升非常明显,尤其是关联Charge数量较多的场景。
拓展场景:批量查询Payment时预求和
如果需要同时查询多个Payment的已支付金额(比如列表页),可以用Laravel 8及以上版本支持的withSum方法,一次查询完成所有求和,避免N+1问题:
// 查询所有payment时直接附带已支付金额属性 $payments = Payment::withSum('charges as paid_amount', 'charge_payment.amount')->get(); // 直接访问属性即可,不需要额外查询 foreach ($payments as $payment) { echo $payment->paid_amount; }
内容的提问来源于stack exchange,提问作者Joro Stoyanov
相关产品推荐
相关产品推荐

