如何实现按用户维度统计并动态展示各用户的佣金总额?
问题核心根因
现在代码从模型到控制器再到视图,全链路都写死了“以当前登录用户为计算目标”的逻辑,根本没有做“按列表行对应用户计算佣金”的分支,所以不管怎么调,最终展示的全是同一个当前登录用户的503,582.26这个数。
具体硬伤点:
- 模型层
gettotalcommi、gettotalWithdrawn两个方法,硬编码从session取当前登录的uid作为查询条件,代码里写的$a = $this->input->post('userID')是完全没用的冗余代码,传任何其他用户ID进去,查询条件还是当前登录人的uid。 - 控制器层是把全局计算出来的两个固定值(当前登录人的总入账、总出账)一次性传给视图,相当于整个页面所有位置用的都是同一个数。
- 视图层循环用户列表的时候,加了
if($rows->uuid===$_SESSION['uid']):的判断,导致只有当前登录用户的行会被渲染,其他用户的行直接被跳过,就算改了计算逻辑也看不到其他用户的数据。
落地修改步骤
1. 重构模型层,把按用户计算佣金的逻辑改成通用方法
把原来写死session查询的方法,改成接收用户ID作为入参的可复用方法,去掉模型里直接读session、读POST的硬编码逻辑,保证传入哪个用户ID,就返回哪个用户的佣金计算结果:
/** * 按用户ID计算对应可结算佣金余额 * @param int|string $user_id 需要查询的用户唯一标识 * @return string 格式化后的佣金金额 */ function get_user_commission_balance($user_id) { // 计算指定用户的累计佣金入账 $this->db->select_sum('amount as total_in'); $this->db->where('commTo', $user_id); $this->db->where_in('commType', ['in']); $total_in = $this->db->get('agent_commission_history')->row()->total_in ?? 0; // 计算指定用户的累计佣金已出账/提现金额 $this->db->select_sum('amount as total_out'); $this->db->where('commTo', $user_id); $this->db->where_in('commType', ['out']); $total_out = $this->db->get('agent_commission_history')->row()->total_out ?? 0; return number_format($total_in - $total_out, 2); }
2. 调整控制器逻辑,删除全局佣金的传参
原来控制器里用来传全局佣金值的两行代码完全没用,直接删掉就行,不需要再把固定的当前用户佣金值传给视图:
public function agents() { $data['activeNav'] = ""; $data['subnav'] = "networks"; $this->header($data); $this->nav(); // 拉取全量(或当前用户下属的)代理列表 $data['result'] = $this->networks->getAllData(); // 删掉原来的全局佣金传参代码: // $data['commBalance']=$this->load->networks->gettotalcommi(); // $data['commWithdrawn']=$this->load->networks->gettotalWithdrawn(); $data['meronResult'] = $this->networks->meronBets(); $data['walaResult'] = $this->networks->walaBets(); $data['tagent']=$this->load->networks->gettotalagent(); $this->load->view('agents', $data); $this->footer(); }
这里要注意:
getAllData()方法的查询逻辑要和页面权限匹配——如果是上级代理看自己的下级列表,那这个方法里应该加条件只返回当前登录用户的下属数据,不要在视图层加判断做过滤。
3. 修改视图层,去掉行过滤逻辑,按行匹配计算佣金
首先删掉那个导致只显示当前登录用户行的判断,保证所有列表行都能正常渲染;然后循环到每一行的时候,拿当前行的用户ID,调用模型方法算对应用户的佣金值,不要用全局变量:
<?php foreach($result as $rows) { $user_unique_id = $rows->uuid; // 要和commTo字段的存储值对应上,是uuid就传uuid,是userID就传userID ?> <!-- 删掉原来的 if($rows->uuid===$_SESSION['uid']): 判断,所有行正常渲染 --> <tr> <td><?php echo $rows->firstname; ?></td> <td><?php echo $rows->mobile; ?></td> <td><?php echo $rows->account_type; ?></td> <td><?php echo $rows->currentPoints; ?></td> <!-- 按当前行的用户ID算对应佣金 --> <td><?php echo $this->networks->get_user_commission_balance($user_unique_id); ?></td> <td>
性能优化建议
如果列表的用户量超过100条,逐行调用方法查数据库会造成额外的SQL开销,拖慢页面加载。可以直接在getAllData()的模型查询里,用左连接子查询一次性把所有用户的佣金余额关联查出来,举个实现片段:
// getAllData方法内的查询逻辑 $this->db->select("u.*, COALESCE(in_stat.total_in, 0) - COALESCE(out_stat.total_out, 0) as commission_balance "); $this->db->from('users as u'); // 关联所有用户的佣金入账汇总 $this->db->join( "(SELECT commTo, SUM(amount) as total_in FROM agent_commission_history WHERE commType = 'in' GROUP BY commTo) as in_stat", 'in_stat.commTo = u.uuid', 'left' ); // 关联所有用户的佣金出账汇总 $this->db->join( "(SELECT commTo, SUM(amount) as total_out FROM agent_commission_history WHERE commType = 'out' GROUP BY commTo) as out_stat", 'out_stat.commTo = u.uuid', 'left' );
这样查出来的每一行用户数据会自带commission_balance字段,视图里直接echo $rows->commission_balance就行,不需要循环里反复查库,加载速度会提升很多。
容易踩的核对点
- 确认
agent_commission_history表的commTo字段存储的用户标识,和用户列表里的uuid/userID是同一种值,不然传错参数会查出来佣金为0的问题。 - 删掉视图层的行过滤判断后,要确认页面权限逻辑正常,不能把不属于当前登录用户管辖的用户数据泄露出去。
内容的提问来源于stack exchange,提问作者Dark
相关产品推荐
相关产品推荐

