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

嵌套While循环查询会议室数据:仅显示单个会议室名称问题排查

问题分析与解决方案

看起来你遇到的核心问题是HTML表格结构不完整导致的渲染异常,同时代码逻辑的排版问题也让浏览器无法正确解析所有会议室数据。浏览器对不规范的表格结构容错性有限,你的代码只输出了<td>单元格,却没有用<tr>(表格行)来包裹每一组数据,结果所有单元格被挤到了同一行,看起来就只有第一个会议室的名称能正常显示。

下面给你两种修正方案,分别对应不同的布局需求:

方案1:每行对应一个会议室的一个时段

如果希望每行显示「会议室名称 + 单个时段状态」,可以这样修改代码,补全完整的表格结构:

<table class="table table-bordered">
  <thead>
    <tr>
      <th>会议室名称</th>
      <th>09:00 时段状态</th>
    </tr>
  </thead>
  <tbody>
    <?php
    $sql2 = $koneksi->query("SELECT id, nama_room FROM ruang_meeting ORDER BY id ASC");
    while ($data = $sql2->fetch_assoc()) {
        $id = $data['id'];
        // 改用预处理语句避免SQL注入风险
        $sql3 = $koneksi->prepare("SELECT * FROM tx_meetingroom WHERE id_ruang=?");
        $sql3->bind_param("i", $id);
        $sql3->execute();
        $result = $sql3->get_result();

        // 处理该会议室无任何时段记录的情况
        if ($result->num_rows === 0) {
    ?>
          <tr>
            <td><?php echo htmlspecialchars($data['nama_room']); ?></td>
            <td><a href='' class='btn btn-primary'><i class='fa fa-check'></i></a></td>
          </tr>
    <?php
        } else {
            while ($data2 = $result->fetch_assoc()) {
    ?>
              <tr>
                <td><?php echo htmlspecialchars($data['nama_room']); ?></td>
                <?php if ($data2['start'] === "09:00:00") { ?>
                  <td><a href='' class='btn btn-danger' disabled><i class='fa fa-ban'></i></a></td>
                <?php } else { ?>
                  <td><a href='' class='btn btn-primary'><i class='fa fa-check'></i></a></td>
                <?php } ?>
              </tr>
    <?php
            }
        }
        $sql3->close();
    }
    ?>
  </tbody>
</table>

方案2:每行对应一个会议室,显示所有时段状态

如果希望更清晰地查看单个会议室的所有时段可用性,可以用LEFT JOIN优化查询,把每个会议室的所有时段状态放在同一行:

<?php
// 获取所有需要显示的时段(如果是固定时段,也可以直接手动定义数组)
$timeSlotsQuery = $koneksi->query("SELECT DISTINCT start FROM tx_meetingroom ORDER BY start ASC");
$timeSlots = $timeSlotsQuery->fetch_all(MYSQLI_ASSOC);
?>

<table class="table table-bordered">
  <thead>
    <tr>
      <th>会议室名称</th>
      <?php foreach ($timeSlots as $slot) { ?>
        <th><?php echo substr($slot['start'], 0, 5); ?> 时段</th>
      <?php } ?>
    </tr>
  </thead>
  <tbody>
    <?php
    // 用JOIN一次性获取所有数据,减少数据库查询次数
    $sql = $koneksi->query("
      SELECT rm.id, rm.nama_room, tx.start
      FROM ruang_meeting rm
      LEFT JOIN tx_meetingroom tx ON rm.id = tx.id_ruang
      ORDER BY rm.id ASC, tx.start ASC
    ");

    $currentRoomId = null;
    $currentRoomName = '';
    $occupiedSlots = [];

    while ($data = $sql->fetch_assoc()) {
        // 切换到新会议室时,先输出上一个会议室的状态行
        if ($data['id'] !== $currentRoomId) {
            if ($currentRoomId !== null) {
    ?>
              <tr>
                <td><?php echo htmlspecialchars($currentRoomName); ?></td>
                <?php foreach ($timeSlots as $slot) { ?>
                  <td>
                    <?php if (in_array($slot['start'], $occupiedSlots)) { ?>
                      <a href='' class='btn btn-danger' disabled><i class='fa fa-ban'></i></a>
                    <?php } else { ?>
                      <a href='' class='btn btn-primary'><i class='fa fa-check'></i></a>
                    <?php } ?>
                  </td>
                <?php } ?>
              </tr>
    <?php
            }
            // 初始化新会议室的状态
            $currentRoomId = $data['id'];
            $currentRoomName = $data['nama_room'];
            $occupiedSlots = [];
        }
        // 记录当前会议室已被占用的时段
        if (!empty($data['start'])) {
            $occupiedSlots[] = $data['start'];
        }
    }

    // 输出最后一个会议室的状态行
    if ($currentRoomId !== null) {
    ?>
      <tr>
        <td><?php echo htmlspecialchars($currentRoomName); ?></td>
        <?php foreach ($timeSlots as $slot) { ?>
          <td>
            <?php if (in_array($slot['start'], $occupiedSlots)) { ?>
              <a href='' class='btn btn-danger' disabled><i class='fa fa-ban'></i></a>
            <?php } else { ?>
              <a href='' class='btn btn-primary'><i class='fa fa-check'></i></a>
            <?php } ?>
          </td>
        <?php } ?>
      </tr>
    <?php } ?>
  </tbody>
</table>

额外优化建议

  • 避免SQL注入:我在方案1中改用了预处理语句,直接拼接变量到SQL里会有安全风险,建议所有数据库操作都使用预处理。
  • 转义输出内容:用htmlspecialchars()转义会议室名称,避免XSS攻击和特殊字符渲染异常。
  • 性能优化:方案2用LEFT JOIN替代嵌套查询,减少了数据库请求次数,在数据量大时性能提升明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:13:53