DataTable中待付总计等于0.00时如何隐藏对应客户数据行
DataTable过滤待付金额为0客户行实现方案
现有实现效果参考:
不要在addColumn列渲染逻辑里处理行隐藏,这个方法只负责单列表格内容的输出,无法控制整行的显示/隐藏,放在前端隐藏还会导致分页计数错乱、空行占位的问题,正确做法是在后端数据查询阶段直接过滤掉待付金额为0的客户数据,同时优化原有的重复计算逻辑,具体实现如下:
1. 修改客户列表查询构建逻辑
在取客户数据的查询层,当检测到请求携带due_filter参数时,直接通过关联查询过滤掉待付总额为0的客户,同时预计算待付金额,避免后续列渲染时重复计算产生冗余查询:
use Illuminate\Support\Facades\DB; // 原有客户查询起始部分 $customerQuery = Customer::query() // 预加载符合状态的发票关联 ->with(['invoices' => function($invoiceQuery) { $invoiceQuery->whereIn('status', ['due', 'partial']); }]) // 触发due_filter时追加过滤和预计算逻辑 ->when(request('due_filter'), function ($query) { // 过滤掉待付总额<=0的客户 $query->whereHas('invoices', function ($invoiceQuery) { $invoiceQuery->whereIn('status', ['due', 'partial']) ->havingRaw('(SUM(total) - SUM(pamnt)) > 0'); }) // 预计算每个客户的待付总额,绑定到客户模型属性上 ->withSum([ 'invoices as total_due' => function($invoiceQuery) { $invoiceQuery->whereIn('status', ['due', 'partial']); } ], DB::raw('total - pamnt')); }); // 后续接你原有的DataTable处理逻辑即可,比如传入datatables()构造器
2. 简化原有addColumn逻辑
因为已经在查询阶段预计算了待付总额,列渲染时不需要再遍历关联发票集合计算,直接取预计算的属性即可,性能更好:
->addColumn('name', function ($customer) { $dueBadge = ''; if (request('due_filter')) { $dueBadge = '<span class="badge badge-danger">' . amountFormat($customer->total_due ?? 0) . '</span>'; } return '<a class="font-weight-bold" href="' . route('biller.customers.show', [$customer->id]) . '">' . $customer->name . '</a>' . $dueBadge; })
注意事项
- 不要在前端DataTable的行绘制回调里隐藏DOM行,会导致分页总数和实际展示行数不匹配,后端过滤是唯一稳妥的方案
- 数据库聚合层直接做金额判断,避开PHP浮点数全等判断
==0.00的精度问题 - 预计算待付金额的写法可以避免N+1查询,客户数据量大时加载速度提升明显
内容的提问来源于stack exchange,提问作者Mo Nabil
相关产品推荐
相关产品推荐

