使用PDO时如何处理for循环内输入为空的错误问题
问题修复方案
存在的核心问题
- 未提前校验
$name数组是否为空,当传入的商品列表为空时,for循环直接跳过无执行逻辑,自然无返回结果 $stmt1仅在循环的插入分支中定义,若所有循环项都不满足插入条件,末尾判断$stmt1时会报未定义变量错误- 循环空跑时仍会执行账单表插入逻辑,会生成无对应商品的无效订单
- 预处理SQL直接拼接变量,存在SQL注入风险
- 订单号生成逻辑存在并发重复风险
- 单条商品校验不通过就直接抛出错误,未处理批量场景下的异常终止逻辑
修复后的代码
public function Add_new_order($tableno, $cashier_name, $date, $time, $name, $quantity, $price, $sub_total, $total) { // 先校验传入的商品数组是否为空 if(empty($name) || !is_array($name) || count($name) == 0) { $this->Error_msg('商品列表不能为空'); return; } // 用事务包裹操作避免数据不一致,加行锁解决订单号并发重复问题 $this->conn->beginTransaction(); try { $stmt = $this->conn->prepare("SELECT MAX(order_num) AS order_number FROM all_orders FOR UPDATE"); $stmt->execute(); $row = $stmt->fetch(); $order_num = $row["order_number"] ?? '100000'; if(is_numeric($order_num)) { $order_num += 1; } $insert_count = 0; // 提前计算数组长度避免循环重复计算 $item_count = count($name); for($i = 0; $i < $item_count; $i++) { // 提前判断下标是否存在避免数组越界报错 if(!isset($quantity[$i]) || !isset($name[$i]) || !isset($price[$i]) || !isset($sub_total[$i])) { continue; } if($quantity[$i] > 0 && $name[$i] != "" && $price[$i] != "") { // 用参数绑定彻底避免SQL注入 $stmt1 = $this->conn->prepare("INSERT INTO `all_orders` (`order_num`, `tablenum`,`cashier_name`, `date`, `time`, `item_name`, `quantity`, `price`, `total`) VALUES (?,?,?,?,?,?,?,?,?)"); $stmt1->execute([ $order_num, $tableno, $cashier_name, $date, $time, $name[$i], $quantity[$i], $price[$i], $sub_total[$i] ]); if($stmt1->rowCount() > 0) { $insert_count++; } } } // 没有成功插入任何商品直接回滚报错 if($insert_count == 0) { $this->conn->rollBack(); $this->Error_msg('没有有效商品可插入'); return; } // 插入账单表 $stmt2 = $this->conn->prepare("INSERT INTO `biling`(`order_num`, `tablenum`,`cashier_name`, `date`, `time`, `total`) VALUES (?,?,?,?,?,?)"); $stmt2->execute([ $order_num, $tableno, $cashier_name, $date, $time, $total ]); if($stmt2->rowCount() > 0) { $this->conn->commit(); $this->Success_msg('Done.'); } else { $this->conn->rollBack(); $this->Error_msg('账单插入失败'); } } catch (Exception $e) { $this->conn->rollBack(); $this->Error_msg('Error occurred:'.$e->getMessage()); } }
额外说明
- 修复后新增了前置空数组校验,空输入时会直接返回错误提示
- 用事务包裹整个操作,避免部分插入成功部分失败导致的数据不一致
- 所有SQL改用参数绑定,彻底避免SQL注入风险
- 新增插入成功计数校验,没有有效商品插入时不会生成空账单
- 自增主键ID无需在插入语句中声明,数据库会自动生成
内容的提问来源于stack exchange,提问作者Hazem Behairy
相关产品推荐
相关产品推荐

