PHP与MySQL航班座位分配逻辑异常:跨日期分配错误求助
修复航空公司座位分配逻辑错误
嘿,我帮你找出了座位分配代码里的两个核心问题,马上就能修复好,赶你的校园项目时间完全没问题!
你的问题是跨日期预订4人时无法分配同一排的连续座位,根源在于SQL查询逻辑错误和全局变量导致的状态残留,具体分析和修复方案如下:
问题1:SQL查询的逻辑优先级错误
你的WHERE子句里,座位检查的OR条件没有正确和前面的航班/日期条件绑定,导致SQL的逻辑运算顺序出错。原代码里的查询:
SELECT * FROM passenger_records WHERE pas_depdate='$date1' AND pas_air='$air' AND pas_frmcity='$from' AND pas_tocity='$to' AND (pas1_seat='$seat' OR pas2_seat='$seat') OR (pas3_seat='$seat' OR pas4_seat='$seat')
因为OR的优先级低于AND,实际执行逻辑变成了:(航班日期条件 AND 前两个座位条件) OR 后两个座位条件——这会导致只要任何一个座位(不管属于哪个航班/日期)被占用,就会返回记录,错误地判定当前座位已被占。
问题2:全局变量导致的座位状态残留
你用了全局变量$seat,每次调用f1()时,这个变量会保留上一次分配的座位值,而不是从1A开始重新检查。比如第一次分配1A后,第二次调用f1()时$seat还是1A,检查到已被占用就跳到1B;第三次调用时$seat是1B,检查到被占用后,你的循环逻辑会错误地跳到下一排的2A,而不是继续检查1C。
修复后的完整代码
<?php function f1() { require 'connection.php'; // 从SESSION获取航班核心参数 $from = $_SESSION['fro']; $to = $_SESSION['to']; $date1 = $_SESSION['dep']; $air = $_SESSION['airl']; $rowNumbers = range(1, 5); // 假设头等舱最多5排,可按需调整 $seatColumns = array("A", "B", "C", "D"); // 从第一排第一个座位开始,依次检查是否被占用 foreach ($rowNumbers as $row) { foreach ($seatColumns as $col) { $currentSeat = $row . $col; // 修正SQL逻辑:所有座位检查用一个括号包裹,确保和航班日期条件是AND关系 $checkQuery = "SELECT * FROM passenger_records WHERE pas_depdate='$date1' AND pas_air='$air' AND pas_frmcity='$from' AND pas_tocity='$to' AND (pas1_seat='$currentSeat' OR pas2_seat='$currentSeat' OR pas3_seat='$currentSeat' OR pas4_seat='$currentSeat')"; $result = $conn->query($checkQuery); // 找到第一个未被占用的座位,直接返回 if ($result->num_rows === 0) { return $currentSeat; } } } // 如果所有座位都被占用,返回空字符串 return ""; } if ($cls == "First Class") { // 为每个乘客分配座位,每次调用f1都会从头检查 if (!empty($pas1)) { $seat1 = f1(); echo $seat1 . "<BR>"; $updateSql = "UPDATE `passenger_records` SET `pas1_seat` = '{$seat1}' WHERE `passenger_records`.`pas_id` = '$id'"; $conn->query($updateSql); } if (!empty($pas2)) { $seat2 = f1(); echo $seat2 . "<BR>"; $updateSql = "UPDATE passenger_records SET pas2_seat = '{$seat2}' WHERE passenger_records.pas_id = '$id'"; $conn->query($updateSql); } if (!empty($pas3)) { $seat3 = f1(); echo $seat3 . "<BR>"; $updateSql = "UPDATE passenger_records SET pas3_seat = '{$seat3}' WHERE passenger_records.pas_id = '$id'"; $conn->query($updateSql); } if (!empty($pas4)) { $seat4 = f1(); echo $seat4 . "<BR>"; $updateSql = "UPDATE `passenger_records` SET `pas4_seat` = '{$seat4}' WHERE `passenger_records`.`pas_id` = '$id'"; $conn->query($updateSql); } } ?>
关键修改说明
- 移除全局变量:用局部变量
$currentSeat替代全局$seat,每次调用f1()都会从1A开始重新遍历,彻底解决状态残留问题。 - 修正SQL逻辑:将所有座位检查条件用一个括号包裹,确保只检查当前航班/日期下的座位占用情况,避免误判。
- 简化遍历逻辑:用嵌套foreach循环替代原有的while+for循环,逻辑更直观,从第一排第一个座位开始,找到第一个空座就返回。
- 规范空值检查:用
!empty()替代!$pas1=="",写法更严谨。
现在测试的话,不管是首次还是其他日期预订4人,都会依次分配1A、1B、1C、1D,完美符合你的预期!
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

