【问题标题】:How can I append an empty array to FormData object?如何将空数组附加到 FormData 对象?
【发布时间】:2017-10-19 11:15:04
【问题描述】:

我有以下问题:

在 FormData 上使用 N 个复选框的 html 表单,用于通过 ajax 发送带有其信息的请求。在 PHP 上,$_POST['teste'] 变量不存在...

<form id="teste_form">
    <input type="checkbox" name="teste[]">
    <input type="checkbox" name="teste[]">
    <input type="checkbox" name="teste[]">
    <input type="checkbox" name="teste[]">...
</form>

<script>
    var form_data_obj = new FormData( document.getElementById('teste_form') );
    $.ajax({
        ...
        data: form_data_obj
        ...
    });
</script>

我知道我可以在 PHP 上使用“if(isset(...))”,但我真的不喜欢那个解决方案。对我来说,最好的解决方案是从 FormData 对象向 PHP 发送一个空数组。

Obs:我试​​过类似的东西,例如:

  • form_data_obj.append('teste[]', undefined).
  • form_data_obj.append('teste[]', 0).

但是没有成功... PHP上的结果分别是:["undefined"], ["0"]

我想在 PHP 中获取 $_POST ['test'] = []

这可能吗?

【问题讨论】:

  • 我宁愿在表单字段名称中指定索引...然后您将通过检查值确切知道属于哪个“位置”。如果你 foreach 在 PHP 中的数组上,那么“丢失”索引不是一个真正的问题。

标签: javascript php ajax form-data


【解决方案1】:

闻起来像这样:How to Submit empty array from HTML Form Post to PHP

解决方法:您可以在客户端使用具有空值的隐藏输入元素,并在服务器端使用空值检查。像这样:

var appended = null;
$('.confirm_appointment').submit(function(e) {

  if (appended !== null) appended.remove();
  /************************************/
  if ($("input[name='teste[]']:checked").length == 0) {
    appended = $("<input type='hidden' name='teste[]' value=''>").appendTo($(this));
  }
  /************************************/

  e.preventDefault();
  $(this).append(decodeURIComponent($(this).serialize()) + '<br />');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name='confirm_appointment' method='post' class='confirm_appointment'>
  <input type='checkbox' name="teste[]" value='hello1' />
  <input type='checkbox' name="teste[]" value='hello2' />
  <input type='checkbox' name="teste[]" value='hello3' />
  <input type='checkbox' name="teste[]" value='hello4' />
  <input type='submit' class='update_appointment_button' value='submit' /><br />
</form>

在 PHP 方面:

$teste = array_filter($_POST["teste"]);

【讨论】:

  • 具有空值的隐藏输入对我有很大帮助,值得一票,但我正在寻找的解决方案是使用 JS,例如 form_data.append ('test', []) 和在 PHP 上接收,无需处理,$ _POST ['test'] = [].
  • 更新了我的答案。
【解决方案2】:

即使没有 jQuery,这也绝对是可能的。

yourFormData.append('key', []);

【讨论】:

  • PHP 错误:array_filter() 期望参数 1 是数组,给定字符串...但即便如此,我的 PHP 代码是通用的。在确定无法通过 FormData 发送空数组之前,我不想更改它。
  • 这与 PHP 无关。表单数据中的空数组会导致空字符串 - 可以在开发人员工具的网络选项卡中看到。
  • 它将字符串附加为 '[]' 但不是空数组。
【解决方案3】:

我不知道这是否相关,但对于我的实现,以下效果很好。在定义了空数组之后,它必须循​​环遍历实际的数组,以递归方式物理声明对象,以适应对象和子数组等...

formData.append(key + '[]', []);

所以在原地使用,我的整个 FormData 构建看起来像这样......

/* ............................................................ */
/* .........runPostFetchScripts Can be used throughout [AF].... */
function runPostFetchScripts(id, str) {
    // Try and break out any scripts that need to also be run from the newly acquired HTML body (these don't naturally get run)...
    // Find ALL script tags (most basic form ONLY for now)...
    //console.log(str);
    scripts = str.split('<sc' + 'ript>');
    // First element will be content, so remove it
    if(scripts.length > 1) {
        scripts.splice(0, 1);
        one_biggy = "";
        for(i = 0; i < scripts.length; ++i) {
            // Then get rid of following content after end of script tag
            scripter = scripts[i].split("</sc" + "ript>");
            // And run what is left...
            //console.log(i + ": " + scripter[0]);
            one_biggy += scripter[0];
        }
        //console.log(one_biggy);
        eval(one_biggy);
    }
    // Phew!  This took way longer than expected [AF]!
}

/* ............................................................ */
/* .........New inclusion for FormData Validation and addition of Files, Multiple Files and Arrays to Form uploads via Ajax.... */
function genericBuildFormData(formData, data, previousKey) {
    /*
    console.log("genericBuildFormData(");
    console.log(formData);
    console.log(data);
    console.log(previousKey);
    //*/
    if(data instanceof File) {
        //console.log(previousKey + " file append...");
        formData.append(previousKey, data);

    } else if (data instanceof Object) {
        var keys = Object.keys(data);
        for(var k = 0; k < keys.length; ++k) {
            var key = keys[k];
            var value = data[key];
            /*
            console.log(k + " " + key);
            console.log(!(value instanceof File));
            console.log(value instanceof Object);
            console.log(!(Array.isArray(value)));
            console.log(value);
            //*/
            if(previousKey != '') {
                key = previousKey + '[' + key + ']';
            }
            if (!(value instanceof File) && (value instanceof Object) && !(Array.isArray(value))) {
                //console.log("Is Object, go again... " + key + "[]");
                formData.append(key + '[]', []);
                genericBuildFormData(formData, value, key);
            } else {
                if (Array.isArray(value)) {
                    //console.log(key + " is Array...");
                    // Define empty array first...
                    formData.append(key + '[]', []);
                    // Now loop through all array contents, accounting for embedded objects and sub-arrays...
                    for (var a = 0; a < value.length; ++a) {
                        //console.log(a);
                        genericBuildFormData(formData, value[a], key + '[' + a + ']');
                    }
                } else {
                    //console.log(key + " append...");
                    formData.append(key, value);
                }
            }
        }
    } else {
        //console.log(previousKey + ": " + data + " append...");
        formData.append(previousKey, data);
    }
}
/* ............................................................ */
/* .............genericAjaxCall Can be used throughout [AF].... */
function genericAjaxCall(GetPost, FullUrl, PostParams, Container, id, callback) {
    /*
    console.log("genericAjaxCall(...");
    console.log(FullUrl);
    console.log(PostParams);
    console.log(Container);
    console.log(id);
    //*/
    var GET_POST = GetPost.toUpperCase();
    var jacks = {
        url: FullUrl,
        type: GET_POST,
        async: true,
        processData: false, // Due to contentType, assume WE have got the data right, so do not allow AJAX to find fault with what we have done (files and arrays will fail otherwise) [AF]
        contentType: false, // Let Ajax work this out for us seeing as we are going to be mixing arrays, objects and files as well as primitives, so don't tell it anything [AF]
        success: function(strResult) {
            populateContainer = (Container ? document.getElementById(Container) : false);
            //console.log(populateContainer);
            if(populateContainer) {
                //populateContainer.innerHTML = ""; // To drop possible scroll values
                populateContainer.innerHTML = strResult;

                //console.log(strResult);
                if(callback != null) {
                    window.setTimeout(function() {
                        callback(id, strResult);
                    }, 100);
                }
            } else {
                //console.log("ajax.strResult: " + FullUrl + " " + id + " = " + strResult);
                if(callback != null) {
                    window.setTimeout(function() {
                        callback(id, strResult);
                    }, 100);
                }
            }
        },
        error: function(jqXHR, textStatus, errorThrown) {
            populateContainer = document.getElementById(Container);
            if(populateContainer) {
                populateContainer.innerHTML = "Error: " + textStatus + " - " + errorThrown;
            } else {
                if(callback != null) {
                    window.setTimeout(function() {
                        callback(id, null, 'Error: ' + textStatus + ' - ' + errorThrown);
                    }, 100);
                } else {
                    console.log('Error: ' + textStatus + ' - ' + errorThrown);
                }
            }
        }
    };
    if(GET_POST == "POST") {
        //console.log(PostParams);
        // Use FormData for File Upload inclusion
        var myFormData = new FormData();
        genericBuildFormData(myFormData, PostParams, '');
        jacks.processData = false;
        jacks.contentType = false;
        jacks.data = myFormData;
    }
    //console.log(jacks);
    $.ajax(jacks);
}

调用代码看起来像这样(它是递归的,所以在考虑发送到 genericBuildFormData 函数的参数时请记住这一点)...

var myFormData = new FormData();
genericBuildFormData(myFormData, PostParams, '');

在 chrome 的“网络标头”(提交时)中查看的结果数据看起来像这样......

additional[]: 
additional[0]: null
additional[1][id]: 7715
additional[1][ex]: Permanent Exclusion
additional[1][mi]: 1
additional[2]: null
additional[3]: null
additional[4]: null

...其中数组元素 0,2,3,4 为空,元素 1 为嵌入对象。

希望这会有所帮助。沙洛姆。

【讨论】:

    猜你喜欢
    • 2023-01-06
    • 2020-12-03
    • 2020-06-23
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-12
    • 2019-03-05
    • 2014-06-13
    相关资源
    最近更新 更多