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

Laravel中如何在whereHas子查询中获取sum('count')?

问题

我有三个模型:Transaction、Cart、Acceptedcart。关联关系如下:

  • Cart 包含 transaction_id 字段,Transaction 与 Cart 是一对多关联:
    // Transaction.php
    public function carts()
    {
        return $this->hasMany(Cart::class);
    }
    
  • Acceptedcart 包含 cart_id 字段,Cart 与 Acceptedcart 是一对多关联:
    // Cart.php
    public function accepted_carts()
    {
        return $this->hasMany(Acceptedcart::class);
    }
    

我已经实现了获取包含未发送(acceptedcart->sended == false)的 Acceptedcart 的 Transaction 查询:

$transactions = Transaction::whereHas('carts.accepted_carts', function ($query) {
    $query->where('sended', false);
})->get();

现在我想获取符合该条件的 Acceptedcart 中 count 列的总和,请问应该把 sum() 放在哪里?以下两种写法是否可行?

写法一:

$transactions = Transaction::whereHas('carts.accepted_carts', function ($query) {
    $query->where('sended', false);
})->sum('count');

写法二:

$transactions = Transaction::whereHas('carts.accepted_carts', function ($query) {
    $query->where('sended', false)->sum('count');
})->get();

是否只能通过遍历 get() 结果的方式来实现?


回答

你给出的两种写法都不可行,原因如下:

  • 写法一:sum('count') 是直接对 transactions 表的 count 字段求和,但你要的是关联的 Acceptedcart 表的 count,表对应错误,结果肯定不符合预期。
  • 写法二:whereHas 的闭包是用来筛选「存在符合条件的关联模型」的逻辑,在闭包里调用 sum() 会直接执行求和查询,破坏了原有的筛选逻辑,最终得到的 $transactions 不是你要的总和,而是不符合要求的模型集合。

不需要必须遍历结果,有更高效的实现方式:

方法一:直接从 Acceptedcart 模型查询(推荐)

既然目标是求和 Acceptedcart 的 count,且条件是该记录关联到 Transaction(对应你之前的 whereHas 逻辑),可以直接反向关联查询:

$totalCount = Acceptedcart::where('sended', false)
    ->whereHas('cart.transaction') // 确保该 Acceptedcart 关联到 Transaction
    ->sum('count');

需要先给 Acceptedcart 补充关联定义:

// Acceptedcart.php
public function cart()
{
    return $this->belongsTo(Cart::class);
}

方法二:用 withSum 统计后汇总

如果你需要先拿到符合条件的 Transaction,再统计它们关联的 Acceptedcart 总和,可以用 Laravel 的 withSum 方法:

$transactions = Transaction::whereHas('carts.accepted_carts', function ($query) {
    $query->where('sended', false);
})->withSum(['carts.accepted_carts' => function ($query) {
    $query->where('sended', false);
}], 'count')->get();

// 汇总所有 Transaction 对应的总和
$totalCount = $transactions->sum('carts_accepted_carts_sum_count');

方法三:遍历结果(仅适合小数据量)

就是你提到的遍历方式,适合数据量不大的场景:

$transactions = Transaction::whereHas('carts.accepted_carts', function ($query) {
    $query->where('sended', false);
})->with('carts.accepted_carts')->get();

$totalCount = 0;
foreach ($transactions as $transaction) {
    foreach ($transaction->carts as $cart) {
        $totalCount += $cart->accepted_carts->where('sended', false)->sum('count');
    }
}

内容的提问来源于stack exchange,提问作者aref razavi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:15:49