一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

怎样在 PHP 中将数据库查询结果按字段分组生成多个子表格

时间:2026-07-07 11:21:58 编辑:袖梨 来源:一聚教程网

本文介绍如何将 postgresql 查询结果按某一字段(如 gene_name)分组,并为每个分组动态生成独立的 html 表格,配合可折叠标题,提升数据展示的结构性与可读性。

本文介绍如何将 postgresql 查询结果按某一字段(如 gene_name)分组,并为每个分组动态生成独立的 html 表格,配合可折叠标题,提升数据展示的结构性与可读性。

在实际 Web 开发中,当查询结果存在重复主键(如多个注释对应同一基因),直接线性输出易造成信息混杂。理想的方案是按 gene_name 分组,为每个基因生成一个专属子表格,并添加语义化标题(如 <h4>gene1</h4> 或交互式折叠按钮)。这不仅提升用户体验,也便于前端样式控制与 JavaScript 操作。

实现的关键在于两次数据处理

  1. 分组聚合:遍历原始查询结果,以 gene_name 为键,将所有相关描述(description)存入嵌套数组;
  2. 结构化渲染:遍历分组后的关联数组,为每个基因名生成独立 <table>,并嵌入其全部描述项。

以下是完整、安全、可运行的优化代码(含防 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免费学习笔记(深入)”;

  • 安全性优先:禁用用户输入直接拼接列名(通过白名单 $allowed_columns 校验),对所有输出内容使用 htmlspecialchars() 防 XSS;
  • SQL 注入防护:pg_escape_string() 仅用于值部分,列名必须硬编码或白名单控制;
  • 空值防御:使用 $line['gene_name'] ?? '' 避免未定义索引警告;
  • ID 合法性:HTML ID 不允许特殊字符,用 preg_replace() 清洗 geneName 生成安全 tableId;
  • 前端兼容性:toggleTable() 函数需自行实现(示例见下方),用于显示/隐藏对应 <div class="content">。

✅ 可选增强(前端折叠逻辑):

<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>

通过这种“先分组、再渲染”的模式,你不仅能精准实现按基因拆分子表格的需求,还构建了可扩展的数据展示架构——未来可轻松增加排序、分页、导出等功能,而无需重构核心逻辑。

热门栏目