如何在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>
关键逻辑说明
- 排序前提:数据库查询时必须添加
ORDER BY booking_reference,保证同预订的学员行连续排列,否则rowspan会错位。 - 状态跟踪:用
$prev_booking_ref记录上一次循环的预订编号,每次循环对比当前编号:- 当编号不同时,说明是新预订的第一行,输出带
rowspan的合并列,值用trainee_total指定跨行数。 - 当编号相同时,跳过合并列的输出,只保留学员相关列,表格会自动利用上一行的
rowspan填充空缺。
- 当编号不同时,说明是新预订的第一行,输出带
- 安全处理:用
htmlspecialchars()转义输出内容,避免XSS风险。
为什么之前直接用trainee_total会混乱?
如果数据未按预订编号排序,或者循环中没有跟踪预订状态,直接给每个行设置rowspan会导致同一个预订的多行都生成带rowspan的单元格,造成表格结构重叠,最终格式错乱。通过对比预订编号控制仅第一行输出合并列,就能彻底解决这个问题。
内容的提问来源于stack exchange,提问作者Matthew Barraud
相关产品推荐
相关产品推荐

