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

Laravel Blade中sortBy与sortByDesc排序致余额计算异常求助

Laravel Blade中sortByDesc排序后余额计算异常的解决方法

在Laravel Blade模板循环交易数据时,用sortBy('created_at')正序排序后,每行期末余额计算正常;但切换为sortByDesc('created_at')倒序排序时,余额结果就会异常。

问题代码示例

@php
    $balance = 0;
@endphp
@foreach($transactions->sortByDesc('created_at') as $transaction)
    <tr data-id="{{ $transaction->id }}"
        data-click-url="{{ $transaction->action_type == 'stock_delivery' ? route('admin.expenses.deliveries.show',$transaction->action_id) : mRoute('edit', $transaction->id) }}">
        <td>{{ date('d.m.Y', strtotime($transaction->paid_at)) }}</td>
        <td>@transUcFirst('generic.financial.payment_types.' .
            PAYMENT_TYPE[$transaction->payment_type])
        </td>
        <td>
            @if($transaction->action_type)
                @if($transaction->action_type == 'sale')
                    <span class="text-danger">@transUcFirst('generic.financial.sale')</span>
                @elseif($transaction->action_type == 'stock_delivery')
                    @trans('models.delivery.delivery_invoice')
                @elseif($transaction->action_type == 'subscription')
                @endif
            @else
                <span class="text-success">Tahsilat</span>
            @endif
        </td>
        <td class="text-right">@currencySymbol <b>{{ tl_format($transaction->amount) }}</b></td>
        <td class="text-right">@currencySymbol {{ tl_format($balance += $transaction->amount) }}</td>
    </tr>
@endforeach

问题原因

余额计算逻辑和遍历顺序不匹配:

  • 正序排序时,从最早的交易开始遍历累加,得到的是每笔交易完成后的真实期末余额,逻辑正确。
  • 倒序排序时,直接从最新交易开始累加,相当于从时间线末尾往回计算,得到的结果并不是每笔交易实际发生后的期末余额,自然出现异常。

解决方案

方案1:控制器预处理数据(推荐)

把余额计算和排序逻辑移到控制器中,避免Blade模板处理复杂逻辑:

// 控制器代码
$balance = 0;
$transactions = Transaction::query()
    ->orderBy('created_at') // 先按时间正序获取交易
    ->get()
    ->map(function ($transaction) use (&$balance) {
        $balance += $transaction->amount;
        $transaction->ending_balance = $balance; // 给每个交易添加预计算的期末余额字段
        return $transaction;
    })
    ->sortByDesc('created_at'); // 最后对交易进行倒序排序

然后在Blade中直接使用预计算好的余额:

@foreach($transactions as $transaction)
    <tr data-id="{{ $transaction->id }}"
        data-click-url="{{ $transaction->action_type == 'stock_delivery' ? route('admin.expenses.deliveries.show',$transaction->action_id) : mRoute('edit', $transaction->id) }}">
        <!-- 其他列保持不变 -->
        <td class="text-right">@currencySymbol {{ tl_format($transaction->ending_balance) }}</td>
    </tr>
@endforeach

方案2:Blade内处理逻辑

如果必须在Blade中处理,先正序遍历计算所有交易的余额并存储,再倒序遍历交易匹配对应余额:

@php
    $balance = 0;
    $transactionBalances = [];
    // 先正序遍历,计算每笔交易的期末余额并存在数组中
    foreach($transactions->sortBy('created_at') as $t) {
        $balance += $t->amount;
        $transactionBalances[$t->id] = $balance;
    }
@endphp

@foreach($transactions->sortByDesc('created_at') as $transaction)
    <tr data-id="{{ $transaction->id }}"
        data-click-url="{{ $transaction->action_type == 'stock_delivery' ? route('admin.expenses.deliveries.show',$transaction->action_id) : mRoute('edit', $transaction->id) }}">
        <!-- 其他列保持不变 -->
        <td class="text-right">@currencySymbol {{ tl_format($transactionBalances[$transaction->id]) }}</td>
    </tr>
@endforeach

内容的提问来源于stack exchange,提问作者Ugur Karagoz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:43:15