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

如何在PHP foreach循环中仅对选定行使用rowspan

实现同预订行的列合并(rowspan)方案

直接通过对比上一次循环的booking_reference来控制合并列的输出是可行的,核心是跟踪当前预订的状态,只在每个预订的第一行输出带rowspan的合并列,后续行跳过这些列即可。关键是要确保数据按booking_reference排序,否则同预订的行分散会导致表格结构混乱。

具体代码实现

<?php
// 模拟数据库返回的预订数据(需确保已按booking_reference排序)
$bookings = [
    (object)[
        'booking_reference' => 'BOOK-001',
        'trainee_total' => 3,
        'booked_by' => 'John Doe',
        'invoices' => 'INV-001, INV-002',
        'balance_to_pay' => '£150',
        'trainee_name' => 'Alice Smith',
        'trainee_email' => 'alice@example.com'
    ],
    (object)[
        'booking_reference' => 'BOOK-001',
        'trainee_total' => 3,
        'booked_by' => 'John Doe',
        'invoices' => 'INV-001, INV-002',
        'balance_to_pay' => '£150',
        'trainee_name' => 'Bob Johnson',
        'trainee_email' => 'bob@example.com'
    ],
    (object)[
        'booking_reference' => 'BOOK-001',
        'trainee_total' => 3,
        'booked_by' => 'John Doe',
        'invoices' => 'INV-001, INV-002',
        'balance_to_pay' => '£150',
        'trainee_name' => 'Charlie Brown',
        'trainee_email' => 'charlie@example.com'
    ],
    (object)[
        'booking_reference' => 'BOOK-002',
        'trainee_total' => 1,
        'booked_by' => 'Jane Smith',
        'invoices' => 'INV-003',
        'balance_to_pay' => '£50',
        'trainee_name' => 'David Wilson',
        'trainee_email' => 'david@example.com'
    ]
];

$prev_booking_ref = null;
?>

<table border="1">
    <thead>
        <tr>
            <th>Trainee Name</th>
            <th>Trainee Email</th>
            <th>Booked by</th>
            <th>Invoices</th>
            <th>Balance to pay</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($bookings as $booking): ?>
            <tr>
                <!-- 学员信息列,每行都输出 -->
                <td><?= htmlspecialchars($booking->trainee_name) ?></td>
                <td><?= htmlspecialchars($booking->trainee_email) ?></td>

                <?php if ($booking->booking_reference !== $prev_booking_ref): ?>
                    <!-- 仅在当前预订的第一行输出合并列 -->
                    <td rowspan="<?= $booking->trainee_total ?>">
                        <?= htmlspecialchars($booking->booked_by) ?>
                    </td>
                    <td rowspan="<?= $booking->trainee_total ?>">
                        <?= htmlspecialchars($booking->invoices) ?>
                    </td>
                    <td rowspan="<?= $booking->trainee_total ?>">
                        <?= htmlspecialchars($booking->balance_to_pay) ?>
                    </td>
                    <!-- 更新上一个预订标识 -->
                    <?php $prev_booking_ref = $booking->booking_reference; ?>
                <?php endif; ?>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>

关键逻辑说明

  1. 排序前提:数据库查询时必须添加ORDER BY booking_reference,保证同预订的学员行连续排列,否则rowspan会错位。
  2. 状态跟踪:用$prev_booking_ref记录上一次循环的预订编号,每次循环对比当前编号:
    • 当编号不同时,说明是新预订的第一行,输出带rowspan的合并列,值用trainee_total指定跨行数。
    • 当编号相同时,跳过合并列的输出,只保留学员相关列,表格会自动利用上一行的rowspan填充空缺。
  3. 安全处理:用htmlspecialchars()转义输出内容,避免XSS风险。

为什么之前直接用trainee_total会混乱?

如果数据未按预订编号排序,或者循环中没有跟踪预订状态,直接给每个行设置rowspan会导致同一个预订的多行都生成带rowspan的单元格,造成表格结构重叠,最终格式错乱。通过对比预订编号控制仅第一行输出合并列,就能彻底解决这个问题。

内容的提问来源于stack exchange,提问作者Matthew Barraud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 18:50:33