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
相关产品推荐
相关产品推荐

