本文介绍如何将 postgresql 查询结果按某一字段(如 gene_name)分组,并为每个分组动态生成独立的 html 表格,配合可折叠标题,提升数据展示的结构性与可读性。
本文介绍如何将 postgresql 查询结果按某一字段(如 gene_name)分组,并为每个分组动态生成独立的 html 表格,配合可折叠标题,提升数据展示的结构性与可读性。
在实际 Web 开发中,当查询结果存在重复主键(如多个注释对应同一基因),直接线性输出易造成信息混杂。理想的方案是按 gene_name 分组,为每个基因生成一个专属子表格,并添加语义化标题(如 <h4>gene1</h4> 或交互式折叠按钮)。这不仅提升用户体验,也便于前端样式控制与 JavaScript 操作。
实现的关键在于两次数据处理:
以下是完整、安全、可运行的优化代码(含防 SQL 注入、HTML 转义与错误处理):
<?phpfunction test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data;}$search_input = test_input($_GET["search_keywords"] ?? '');$searched_by = test_input($_GET["search_by"] ?? '');// ✅ 严格校验搜索字段,防止列名注入$allowed_columns = ['gene_name', 'description'];if (!in_array($searched_by, $allowed_columns)) { die('Invalid search column');}// ✅ 使用参数化查询思想(PostgreSQL 中需结合 pg_query_params)// 注意:SIMILAR TO 不支持原生参数绑定,故使用 pg_escape_string + 白名单校验双重防护$escaped_input = pg_escape_string(strtolower($search_input));$query = "SELECT gene_name, description FROM gene WHERE lower($searched_by) ~* '" . $escaped_input . "'";$res = pg_query($query) or die('Query failed: ' . pg_last_error());if (!$res || pg_num_rows($res) === 0) { echo "<p>No results found.</p>n";} else { // ? 第一步:按 gene_name 分组聚合数据 $geneAnnotations = []; while ($line = pg_fetch_assoc($res)) { $geneName = $line['gene_name'] ?? ''; $desc = $line['description'] ?? ''; // 自动去重可选:$geneAnnotations[$geneName][] = $desc; $geneAnnotations[$geneName][] = ['desc' => htmlspecialchars($desc)]; } // ? 第二步:逐组渲染子表格(带折叠功能) foreach ($geneAnnotations as $geneName => $annotations) { $tableId = 'tblAnnotations_' . preg_replace('/[^a-zA-Z0-9_]/', '_', $geneName); echo "<button class="collapsible" data-table-id="$tableId" onclick="toggleTable('$tableId')">"; echo htmlspecialchars($geneName); echo "</button>n"; echo "<div class="content">n"; echo "<table id="$tableId" class="table annot_table">n"; echo "<thead><tr><th>Term</th></tr></thead>n<tbody>n"; foreach ($annotations as $annotation) { echo "<tr><td>{$annotation['desc']}</td></tr>n"; } echo "</tbody>n</table>n"; echo "</div>n"; }}pg_free_result($res);?>
? 关键注意事项:
立即学习“PHP免费学习笔记(深入)”;
✅ 可选增强(前端折叠逻辑):
<script>function toggleTable(id) { const content = document.querySelector(`[data-table-id="${id}"]`).nextElementSibling; content.style.display = content.style.display === 'none' ? 'block' : 'none';}// 初始化默认收起document.querySelectorAll('.content').forEach(el => el.style.display = 'none');</script>
通过这种“先分组、再渲染”的模式,你不仅能精准实现按基因拆分子表格的需求,还构建了可扩展的数据展示架构——未来可轻松增加排序、分页、导出等功能,而无需重构核心逻辑。