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

Laravel中按降序展示流水记录时如何正确计算累计余额

问题修复方案

你现有代码的核心问题是在单个交易模型上误用了sum('amount')方法,该方法是查询构造器/集合的聚合方法,用在单条记录上会全局求和所有流水的金额,而非读取当前交易的金额,最终导致余额计算完全不符合预期。

修复后的代码如下:

1. Controller 部分无需修改

保持原有按创建时间升序取数逻辑即可:

$ledgerTransactions = LedgerRecord::where('ledger_id', $id)->orderBy('created_at', 'asc')->get();

2. Blade 部分修正逻辑

@php
  $balance = 0;
  $ledgerTransactions = $ledgerTransactions->map(function($transaction) use(&$balance) {
    // 直接取当前交易的金额,不要调用sum方法
    $transactionTotal = $transaction->amount;
    // 支付类型金额记为负数
    if ($transaction->type == "Payment") {
      $transactionTotal *= -1;
    }
    // 从最早交易开始累加余额
    $transaction->balance = ($balance += $transactionTotal);
    return $transaction;
  // 余额计算完成后再倒序,让最新交易排在列表顶部
  })->reverse();
@endphp

@foreach($ledgerTransactions as $transaction)
    <tr>
        <td>
            <p class="mb-0">{{ $transaction->created_at->format('M d, Y') }}</p>
        </td>
        <td class="font-weight-bold">{{ $transaction->type }}</td>
        <td>{{ $transaction->description ?? '' }}</td>
        <td>
            ${{ $transaction->amount }}
        </td>
        <td>
            ${{ $transaction->balance }}
        </td>
    </tr>
@endforeach

逻辑说明

  • 从数据库取数时按创建时间升序,保证拿到的是从最早到最新的交易顺序
  • 遍历计算余额时从最早的交易开始累加,每条记录的balance字段就是截止到该笔交易的累计余额
  • 所有余额计算完成后再反转集合,此时最新的交易排在列表最顶部,对应的余额就是截止到最新的总余额,最底部的最早交易对应第一笔交易后的余额,完全符合需求

优化建议

建议把余额计算逻辑移到Controller中处理,不要放在Blade模板内,更符合MVC分层规范。

内容的提问来源于stack exchange,提问作者Ihtisham Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 14:36:05