PHP动态表格提交仅保存最后一行数据问题求助
问题排查与解决方法
核心问题分析
提交表单仅最后一行数据保存、其余丢失,是前端DOM选择逻辑错误和PHP数组处理逻辑错误共同导致的,具体如下:
1. 前端问题:重复ID导致计算失效
动态生成表格行时,所有输入框使用了相同的id属性(如#price、#unit),但HTML中id必须唯一。getInput()函数里用currentRow.querySelector("#unit")只会匹配页面中第一个带该ID的元素,导致后续行的价格计算无法正确赋值,部分数据未填充就提交到后端。
2. PHP问题:数组处理错误导致数据丢失
mysqli_real_escape_string()仅能处理字符串,直接传入数组(如$_POST['Product_name'])会将数组强制转换为字符串"Array",而非逐个转义数组元素。- 插入SQL时未使用数组索引(如
$Product_name[$x]),直接传入整个数组变量,导致每次插入的都是无效值或最后一行数据。
分步修正方案
第一步:修复前端JS与HTML
修改JavaScript代码
移除重复ID,改用类选择器定位当前行的输入框:
const tBody = document.getElementById("table-body"); // 新增行:移除所有重复id,仅保留class addNewRow = () => { const row = document.createElement("tr"); row.className = "single-row"; row.innerHTML = `<td><a class="cut">-</a> <textarea placeholder="Product name" name="Product_name[]" class="product left" style="resize: none; overflow: hidden; width:100%;"></textarea></td> <td><input type="number" placeholder="0" name="price[]" class="price" onkeyup="getInput()"></td> <td><input type="number" placeholder="0" name="unit[]" class="unit" onkeyup="getInput()"></td> <td><input type="number" placeholder="0" name="amount[]" class="amount" readonly="readonly"></td>`; tBody.insertBefore(row, tBody.firstChild); }; document.getElementById("add-row").addEventListener("click", (e) => { e.preventDefault(); addNewRow(); }); // 计算单行总价:改用class选择器定位当前行元素 getInput = () => { var rows = document.querySelectorAll("tr.single-row"); rows.forEach((currentRow) => { var unit = currentRow.querySelector(".unit").value; var price = currentRow.querySelector(".price").value; const amount = unit * price; currentRow.querySelector(".amount").value = amount || 0; overallSum(); }); }; // 计算总价:优化空值处理 overallSum = () => { var arr = document.getElementsByName("amount"); var total = 0; var Amount_paid = document.getElementById('Amount_paid')?.value || 0; for(var i = 0; i < arr.length; i++) { if(arr[i].value) { total += +arr[i].value; } document.getElementById("total").value = total; document.getElementById("Final_Balance").value = total - Amount_paid; } };
修改HTML初始行
移除初始行的重复ID:
<form action="Create_Quote.php" method="POST"> <div class="invoice-body"> <table class="inventory"> <thead> <th>Description</th> <th>Unit Price</th> <th>Quantity</th> <th>Total</th> </thead> <tbody id="table-body"> <tr class="single-row"> <td><a class="cut">-</a> <textarea placeholder="Product name" name="Product_name[]" class="product left" style="resize: none; overflow: hidden; width:100%;"></textarea> </td> <td><input type="number" placeholder="0" name="price[]" class="price" onkeyup="getInput()"></td> <td><input type="number" placeholder="0" name="unit[]" class="unit" onkeyup="getInput()"></td> <td><input type="number" placeholder="0" name="amount[]" class="amount" readonly="readonly"></td> </tr> </tbody> </table> <a href="#" class="add" id="add-row"><span>+</span></a> </div> <button type="submit" name="submit" class='Create not_to_print' id='do-create'>Create</button> </form>
第二步:修复PHP逻辑并优化安全性
修改PHP代码
- 循环处理数组元素,逐个转义
- 使用预处理语句避免SQL注入(替代直接拼接SQL)
if(isset($_POST['submit'])){ // 获取invoice值(假设表单中包含该字段) $invoice = mysqli_real_escape_string($connection, $_POST['invoice']); // 获取表单数组,兼容空值情况 $productNames = $_POST['Product_name'] ?? []; $prices = $_POST['price'] ?? []; $units = $_POST['unit'] ?? []; $amounts = $_POST['amount'] ?? []; // 预处理SQL:使用占位符避免注入风险 $stmt = mysqli_prepare($connection, "INSERT INTO products (invoice, product_name, price, unit, amount) VALUES (?, ?, ?, ?, ?)"); mysqli_stmt_bind_param($stmt, "sdddd", $invoice, $prodName, $price, $unit, $amount); // 循环插入每一行数据 $rowCount = count($productNames); for($x = 0; $x < $rowCount; $x++){ // 跳过空行(可选,根据业务需求调整) if(empty(trim($productNames[$x]))) continue; // 逐个转义数组元素 $prodName = mysqli_real_escape_string($connection, $productNames[$x]); $price = mysqli_real_escape_string($connection, $prices[$x]); $unit = mysqli_real_escape_string($connection, $units[$x]); $amount = mysqli_real_escape_string($connection, $amounts[$x]); // 执行插入操作 mysqli_stmt_execute($stmt); } // 关闭预处理语句 mysqli_stmt_close($stmt); }
关键注意事项
- HTML中
id必须唯一,动态生成元素时仅使用class或其他属性定位。 - 处理表单数组时,不能直接对整个数组使用
mysqli_real_escape_string(),需逐个处理元素。 - 始终使用预处理语句编写SQL,彻底避免SQL注入风险。
内容的提问来源于stack exchange,提问作者Haidi Elnagdy
相关产品推荐
相关产品推荐

