accordion组件加载两表关联用户数据重复渲染问题求助
问题原因
你遇到的重复渲染问题核心是渲染逻辑错误,和SQL语句本身无关:
- 外层
while循环每读取一条联表查询的扁平化结果(1个用户对应1条FTP记录为一行结果),就输出一次accordion按钮,当一个用户绑定多条FTP记录时,同一个用户的按钮会被输出多次。 - 循环过程中持续把当前行追加到
$rows数组,再遍历整个数组输出内容,会导致FTP明细随着循环推进不断累积重复。 - 面板容器内部错误嵌套了第二层
.panel标签,会导致原有JS逻辑找错折叠目标,交互失效。 - 按钮文本硬编码写死为
John Doe,没有动态读取查询返回的真实用户名。 - 单条FTP记录被重复输出了两次,会导致同一条明细显示两遍。
修复方案
原有JS交互、CSS样式代码不需要修改,只需要调整PHP渲染逻辑:先把联表查询的结果按用户ID分组归集,再外层遍历用户输出折叠按钮,内层遍历对应用户的所有FTP明细即可。
修复后的PHP代码如下:
<?php $stmt = $con->prepare("SELECT customers.customer_id, customers.customer_name, customers.customer_company, customers_details.ftp_host, customers_details.ftp_username, customers_details.ftp_password FROM customers LEFT JOIN customers_details ON customers.customer_id = customers_details.customer_id WHERE customers.customer_id > ? ORDER BY customers.customer_company ASC"); $biggerThan = 0; $stmt->bind_param("i", $biggerThan); $stmt->execute(); $result = $stmt->get_result(); $num_rows = mysqli_num_rows($result); $groupedCustomers = []; if ($num_rows > 0) { while ($row = $result->fetch_assoc()) { $cid = $row['customer_id']; // 首次遇到该用户时初始化用户基础信息 if (!isset($groupedCustomers[$cid])) { $groupedCustomers[$cid] = [ 'customer_name' => $row['customer_name'], 'customer_company' => $row['customer_company'], 'ftp_list' => [] ]; } // 归集FTP明细,跳过左连接无匹配的空记录 if (!empty($row['ftp_host'])) { $groupedCustomers[$cid]['ftp_list'][] = [ 'ftp_host' => htmlentities($row['ftp_host']), 'ftp_username' => htmlentities($row['ftp_username']), 'ftp_password' => htmlentities($row['ftp_password']) ]; } } } // 统一渲染页面 if (empty($groupedCustomers)) { echo '<div class="alert alert-danger" role="alert">No user details found</div>'; } else { foreach ($groupedCustomers as $customer) { ?> <button class="accordion"><?= htmlentities($customer['customer_name']) ?></button> <div class="panel"> <?php foreach ($customer['ftp_list'] as $index => $ftp): ?> <p>FTP Host: <?= $ftp['ftp_host'] ?></p> <p>FTP Username: <?= $ftp['ftp_username'] ?></p> <p>FTP Password: <?= $ftp['ftp_password'] ?></p> <?php if ($index !== array_key_last($customer['ftp_list'])): ?> <hr> <?php endif; ?> <?php endforeach; ?> </div> <?php } } ?>
修复说明
- 新增数据分组逻辑:联表查询返回的是用户和FTP明细一对一的扁平化结果,先按用户ID归集后,每个用户只会输出一次折叠按钮,从根源解决重复显示问题。
- 移除了面板内部嵌套的多余
.panel标签,保证原有JS逻辑可以正确定位到按钮对应的折叠面板,交互正常生效。 - 按钮文本动态读取用户名,所有输出到页面的动态内容都做了html转义,避免XSS风险。
- 去掉了单条FTP记录重复输出的冗余代码,分隔线仅在两条FTP明细中间显示,不会在最后一条明细下方出现多余横线。
- 兼容左连接场景:如果用户没有绑定任何FTP记录,不会输出空白无效内容。
内容的提问来源于stack exchange,提问作者5admin
相关产品推荐
相关产品推荐

