You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP管理HTML表子记录及在DataTable中实现子记录折叠展示

在DataTable中展示关联子记录并实现折叠功能(PHP+JS/jQuery方案)

刚好我之前做过类似的需求,给你分享一个完整的实现方案,涵盖PHP数据处理和DataTable的子行折叠功能:

第一步:PHP端预处理关联数据

你当前的SQL查询返回的是扁平结果(每条子记录对应一条主记录),直接渲染会导致主公司名称重复显示。所以第一步要把数据按主公司分组,把子记录聚合到对应的主记录下:

// 假设你已经通过PDO/mysqli执行查询,获取到结果集$rows
$groupedData = [];
foreach ($rows as $row) {
    $companyName = $row['companyName'];
    // 初始化主记录(如果还不存在)
    if (!isset($groupedData[$companyName])) {
        $groupedData[$companyName] = [
            'companyName' => htmlspecialchars($companyName),
            'subRecords' => []
        ];
    }
    // 添加子记录,注意转义防止XSS
    $groupedData[$companyName]['subRecords'][] = [
        'Name' => htmlspecialchars($row['Name']),
        'Mobile' => htmlspecialchars($row['Mobile'])
    ];
}
// 转换为索引数组,方便前端处理
$groupedData = array_values($groupedData);

第二步:前端渲染DataTable并实现折叠功能

我们会用DataTable官方的row.child() API来实现子行折叠,配合jQuery处理点击事件:

HTML结构

先渲染主表格的框架,只显示主公司信息:

<table id="companyTable" class="display" style="width:100%">
    <thead>
        <tr>
            <th></th> <!-- 预留折叠按钮列 -->
            <th>公司名称</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($groupedData as $company): ?>
        <tr>
            <td></td>
            <td><?php echo $company['companyName']; ?></td>
        </tr>
        <?php endforeach; ?>
    </tbody>
</table>

JavaScript/jQuery逻辑

初始化DataTable并绑定折叠点击事件:

$(document).ready(function() {
    // 初始化DataTable
    const table = $('#companyTable').DataTable({
        columnDefs: [
            {
                className: 'details-control', // 给折叠按钮列加专属样式
                orderable: false, // 禁止该列排序
                targets: 0
            }
        ],
        order: [[1, 'asc']] // 默认按公司名称升序排序
    });

    // 绑定折叠按钮的点击事件
    $('#companyTable tbody').on('click', 'td.details-control', function () {
        const tr = $(this).closest('tr');
        const row = table.row(tr);
        // 获取当前行的公司名称,用来匹配子记录
        const companyName = tr.find('td:eq(1)').text();
        // 从预加载的分组数据中找到对应公司
        const targetCompany = <?php echo json_encode($groupedData); ?>.find(item => item.companyName === companyName);

        if (row.child.isShown()) {
            // 子行已展开,收起它
            row.child.hide();
            tr.removeClass('shown');
        } else {
            // 构建子记录表格的HTML
            let subTableHtml = '<table class="sub-table" style="width:100%">';
            subTableHtml += '<thead><tr><th>姓名</th><th>手机号</th></tr></thead><tbody>';
            targetCompany.subRecords.forEach(sub => {
                subTableHtml += `<tr><td>${sub.Name}</td><td>${sub.Mobile}</td></tr>`;
            });
            subTableHtml += '</tbody></table>';
            
            // 展开子行并插入内容
            row.child(subTableHtml).show();
            tr.addClass('shown');
        }
    });
});

样式优化(可选)

给折叠按钮和子表格加一点样式,提升交互体验:

/* 折叠按钮的图标样式 */
td.details-control {
    background: url('https://datatables.net/examples/resources/details_open.png') no-repeat center center;
    cursor: pointer;
    width: 20px;
}
tr.shown td.details-control {
    background: url('https://datatables.net/examples/resources/details_close.png') no-repeat center center;
}

/* 子表格样式 */
.sub-table {
    margin: 10px 30px;
    border-collapse: collapse;
}
.sub-table th, .sub-table td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: left;
}
.sub-table th {
    background-color: #f5f5f5;
}

关键说明

  • PHP分组的意义:避免前端重复处理相同的主记录,同时减少DOM元素数量,提升页面性能。
  • XSS防护:用htmlspecialchars()转义所有输出到页面的文本,防止跨站脚本攻击。
  • DataTable API的优势:官方的row.child()方法已经封装了子行的显示/隐藏逻辑,不需要自己手动处理DOM的复杂操作。

内容的提问来源于stack exchange,提问作者patel jay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:05:59