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

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代码

  1. 循环处理数组元素,逐个转义
  2. 使用预处理语句避免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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:19:52