返回

动态表格新增行时PHP和JavaScript输入更新问题的解决方案

php

动态表格新增行时PHP和JavaScript输入更新问题

在处理数据库中的数据(例如日记账分项)时,使用 JavaScript 动态添加表格行可能会导致 PHP 后端无法正确获取新增输入值。具体表现为:修改现有数据正常,但添加新行后提交表单,新增行的输入值在 $_POST 数组中丢失,导致更新失败,甚至出现 "An error occurred while processing the data. Please try again." 等错误信息。

问题分析

这个问题的核心在于 JavaScript 动态添加的 HTML 元素,在页面提交时,其值不会自动包含在 $_POST 数组中。PHP 接收表单数据依赖于浏览器提交的表单结构,而 JavaScript 动态修改 DOM 结构并不会更新初始的表单结构。因此,服务器端无法识别动态添加的输入字段。

解决方案

方案一:利用 FormData 对象

FormData 对象可以模拟表单提交,将动态添加的输入值也包含进去。通过 FormData,我们可以手动添加表单数据,包括动态生成的输入字段的值。

JavaScript 代码示例:

$("#add-btn").click(function() {
    // ... existing code for appending the new row ...

    // After adding the row, attach a submit handler to the form.
    $('form').submit(function(e) {
        e.preventDefault(); // Prevent default form submission
        const formData = new FormData(this);

        $.ajax({
            url: 'your_php_script.php',  // Replace with your PHP script URL
            type: 'POST',
            data: formData,
            processData: false,  // Important: Prevents jQuery from processing the data
            contentType: false,  // Important: Prevents jQuery from setting content type
            success: function(response) {
                // Handle success, e.g., display a success message or update the table
                console.log(response);
            },
            error: function(xhr, status, error) {
                // Handle error, e.g., display an error message
                console.error(error);
            }
        });
    });
});

操作步骤:

  1. 将 JavaScript 代码中的 your_php_script.php 替换为你实际的 PHP 脚本路径。
  2. 确保表单提交事件绑定到 form 元素,而不是 submit 按钮本身。

PHP 代码修改: 不需要对 PHP 代码进行修改,因为它仍然通过 $_POST 数组接收数据。 FormData 会模拟标准的表单提交。

方案二:使用 Ajax 提交数据

可以直接使用 Ajax 发送数据到服务器。收集所有输入字段的值,包括动态添加的,然后使用 Ajax 将数据发送到 PHP 脚本。

JavaScript 代码示例:

$("#add-btn").click(function(e) {
    // ... your existing row adding code
    // Update your Form Submit Handler
    $("form").on('submit',function(e) {
        e.preventDefault(); // prevent normal form posting behavior

       const data = {};
      $(this).serializeArray().forEach(item => { data[item.name] = item.value });

    $.ajax({
       url:"update_journal.php",  // update to your processing file name
        type:'POST',
        data: data,
         success:function(result)
             console.log(result);
        });
    });
    // Add the dynamic field name attribute "[]".   e.g. name="account[]"  name="debtor[]" name="description[]" ...etc


});


// remove-tr function if needed.   (For deleting a dynamic table row):
$(document).on('click', '.remove-tr', function() {
        $(this).parents('tr').remove();
});

操作步骤:

  1. 用你实际的 PHP 处理文件名替换 update_journal.php
  2. 确保动态添加的输入字段拥有 name 属性,并且以 [] 结尾(例如 name="account[]"name="debtor[]" 等)。
  3. 调整 Ajax 成功和错误处理函数根据你的需求。

PHP 代码修改 (针对方案二): 由于不再使用 [] 的数组形式提交,所以PHP端的处理需要循环获取每一个传入的数据。

// 使用 foreach 循环迭代接收的数据
foreach ($_POST['account'] as $key => $value) {

$s_account = htmlspecialchars(strip_tags($antiXss->xss_clean($_POST['account'][$key])));
    $s_debtor = filter_var($_POST['debtor'][$key], FILTER_SANITIZE_NUMBER_INT);
    // ...其他字段的处理...
}


// Or, Use PHP's array_combine():



// Ensure that both $_POST['account'], $_POST['debtor'], etc. arrays exist and are equal
if (count($_POST['account']) !== count($_POST['debtor']) && count($_POST['account'])!== count($_POST['creditor'])) {
 // Display error message or take appropriate action. Handle the different sizes of input.
  }

  $account= $_POST["account"]; 
$debtor = $_POST["debtor"]; 
$creditor = $_POST["creditor"];
$description= $_POST["description"]; 
$acc_serial = $_POST["acc_serial"]; 


// Example. If you already checked the sizes, and both sizes are equal.

$accountDebtorCombined = array_combine($account, $debtor);

//Loop
foreach ($accountDebtorCombined as $account_index => $debtor_value)
 {
  $s_account = htmlspecialchars(strip_tags($antiXss->xss_clean($account[$account_index])));
    $s_debtor = filter_var($debtor[$account_index], FILTER_SANITIZE_NUMBER_INT);
  $s_creditor = filter_var($creditor[$account_index], FILTER_SANITIZE_NUMBER_INT); 
   $s_description = htmlspecialchars(strip_tags($antiXss->xss_clean($description[$account_index])));
 $s_acc_serial= htmlspecialchars(strip_tags($antiXss->xss_clean($acc_serial[$account_index])));


  if ($s_account== "" ||  $s_debtor== null || $s_creditor== null)
  {

        echo '<script> $(document).ready(function(){ toastr.error("Please fill in all fields"); }) </script>';
 $has_error=true; break;
   }


 if ( $s_debtor== $s_creditor){

        echo '<script> $(document).ready(function(){ toastr.error("Debtor and Creditor cannot be equal in the same row"); }) </script>';
 $has_error=true; break;
 }


 }


// ... Continue with rest of the fields

安全建议:

  • 始终对用户输入进行验证和过滤,防止跨站脚本攻击 (XSS) 和 SQL 注入。使用预处理语句或参数化查询是防止 SQL 注入的最佳实践.
  • 使用 CSRF 令牌来防止跨站请求伪造 (CSRF) 攻击。

选择哪种方案取决于具体项目的需求和复杂度. FormData 方法更简洁,而 Ajax 方法提供更精细的控制. 选择适合你项目的方案并正确实现即可解决动态表格输入更新的问题.