【问题标题】:jQuery - send multidimensional form data to PHP scriptjQuery - 将多维表单数据发送到 PHP 脚本
【发布时间】:2019-02-26 16:21:34
【问题描述】:

我有一个 jQuery 脚本,每当某个 .class 输入发生变化时,它就会将隐藏的输入添加到表单中。根据用户输入,它会为其他不可编辑的列生成值,这些列也会作为隐藏输入推送到表单中。

表单输出如下所示:

<input type="hidden" name="[1008016BSTL][1][part]" value="1008016BSTL" />
<input type="hidden" name="[1008016BSTL][1][price]" value="123" />
<input type="hidden" name="[1008016BSTL][1][priceExVat]" value="102.50" />
<input type="hidden" name="[1008016BSTL][1][fee]" value="10.53" />
<input type="hidden" name="[1008016BSTL][1][profit]" value="68.41" />

这只是我试图捕获的一组数据,但其他数据相同,保存原始密钥和子密钥。

我的表单包装器如下所示:

<form method="post" id="submit-form" enctype="multipart/form-data">
    <input type="submit" value="Save" />
</form>

我的 AJAX 看起来像:

$('form#submit-form').submit(function(e)
{
    e.preventDefault();

    let data = $('form#submit-form').serializeArray();

    $.ajax({
       url: '/save-pricing.php',
       data: {data: JSON.stringify(data)},
       type: 'post',
       success: function(res)
       {
           console.log(res)
       },
       error: function(res)
       {
           alert('Error! I won\'t tell you what it is. But, I\'ll give you a clue: 21');
           console.log(res)
       }
   })
})

我也试过(设置数据):

let data = $('form#submit-form').serialize();
data = JSON.stringify(data);

$.ajax({
    ...
    data: {data: data}
    ...
})

以及省略.stringify() 函数。

这对 PHP 来说是这样的:

<?php
    echo '<pre>'. print_r($_POST, 1) .'</pre>';

    /**
     * Below is for .serialize() -> output is an empty array
     *
     * parse_str($_POST['data'], $postData)
     * echo '<pre>'. print_r($postData, 1) .'</pre>';
     */

使用.serializeArray() 简化输出(仅删除其他集合):

Array
(
    [data] => [
        {"name":"[1008016BSTL][1][part]","value":"1008016BSTL"},
        {"name":"[1008016BSTL][1][price]","value":"123"},
        {"name":"[1008016BSTL][1][priceExVat]","value":"102.50"},
        {"name":"[1008016BSTL][1][fee]","value":"10.53"},
        {"name":"[1008016BSTL][1][profit]","value":"68.41"}
    ]
)

我想这没问题,我可能可以按名称分组并合并到一个数组中,但感觉它应该已经在 jQuery 端使用 .serialize(),然后在 PHP 端使用 parse_str()

但是,正如我所提到的,parse_str().serialize() 产生一个空数组,我不能使用它。

所以我的问题是:如何通过 jQuery 成功地将多维表单数据发送到 PHP?

编辑

添加:

dataType: 'json'

使用.serialize() 然后JSON.stringify(data),删除parse_str() 并输出:

Array
(
    [\"] => Array
    (
        [1008016BSTL] => Array 
        (
            [1] => Array
            (
                [part] => 1008016BSTL
            )
        )
    )
)

【问题讨论】:

    标签: php jquery ajax forms


    【解决方案1】:

    serializeArray 不能很好地处理带括号的输入字段名称。下面的代码将创建一个适当的多维数组,您可以将其发送回服务器。

    $('form#submit-form').submit(function(event)
    {
        event.preventDefault();
        //Prevent the form from submitting
    
        var fields = {};
        //This is where you're gonna store your form fields
    
        $.each($('form#submit-form').serializeArray(), function(i, field) {
            //Get values, even from multiple-selects
            if (Array.isArray(fields[field.name])) {
                fields[field.name].push(field.value);
            } else if (typeof fields[field.name] !== 'undefined') {
                var val = fields[field.name];
                fields[field.name] = new Array();
                fields[field.name].push(val);
                fields[field.name].push(field.value);
            } else {
                fields[field.name] = field.value;
            }
        });
        //Now all the fields are in the fields object
    
        //You're now going to translate "key[subkey]" string to key[subkey] object
        for (var key in fields) {
            var parts = key.split(/[[\]]{1,2}/);
            parts.length--;
            if (parts.length) {
                var val = fields[key];
                delete fields[key];
                addToTree(fields, parts);
                setToValue(fields, val, parts);
            }
            //input field array names (with brackets) are mistakenly treated as strings, this fixes it
        }
    
    
        $.ajax({
            url: '/save-pricing.php',
            data: JSON.stringify(fields),
            contentType: 'application/json',
            type: 'post',
            success: function(res) {
                console.log(res)
            },
            error: function(res) {
                alert('Error! I won\'t tell you what it is. But, I\'ll give you a clue: 21');
                console.log(res)
            }
        })
    });
    
    /**
     * Adds values to a tree.
     * @link https://stackoverflow.com/questions/3663096/how-to-convert-array-to-tree
     */
    function addToTree(tree, array) {
        for (var i = 0, length = array.length; i < length; i++) {
            tree = tree[array[i]] = tree[array[i]] || {}
        }
    }
    
    /**
     * Sets object values.
     * @link https://stackoverflow.com/questions/13719593/how-to-set-object-property-of-object-property-of-given-its-string-name-in-ja
     */
    function setToValue(obj, value, path) {
        for (i = 0; i < path.length - 1; i++) {
            obj = obj[path[i]];
        }
        obj[path[i]] = value;
    }
    

    PHP 端使用json_decode:

    $data = json_decode(file_get_contents('php://input'), true);
    echo '<pre>'. print_r($data, 1) .'</pre>';
    

    【讨论】:

    • 它有几个错误——特别是setToValue 函数中的i is not defined,但它让我足够接近以找出其余的错误。谢谢+1
    【解决方案2】:

    对于您的特定问题,您可以jquery.serializeJSON

    这里是他们的github链接https://github.com/marioizquierdo/jquery.serializeJSON

    这将创建正确的 json 对象。

    【讨论】:

    • 我确实在另一个 SO 帖子上找到了这个答案,但它没有帮助:/
    • 它似乎不像我想要的那样做多维数组
    【解决方案3】:

    这是我针对这种情况的最简单解决方案。

    <?php if(isset($_POST["data"])) {
    
        $post_data = urldecode($_POST["data"]);
    
        parse_str($post_data, $form_data);
    
        // this will give you first element of array by eliminating double quote key ('') in post data array, which is also desired
        $form_data = reset($form_data);
    
        echo '<pre>'; print_r($form_data); echo '</pre>'; exit;
    
    } else { ?>
    
    <form method="post" id="submit-form">
        <input type="hidden" name="[1008016BSTL][1][part]" value="1008016BSTL" />
        <input type="hidden" name="[1008016BSTL][1][price]" value="123" />
        <input type="hidden" name="[1008016BSTL][1][priceExVat]" value="102.50" />
        <input type="hidden" name="[1008016BSTL][1][fee]" value="10.53" />
        <input type="hidden" name="[1008016BSTL][1][profit]" value="68.41" />
        <input type="submit" value="Save" />
    </form>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script type="text/javascript">
        $("#submit-form").on('submit', function(e){
            e.preventDefault();
            var form_data = $("#submit-form").serialize();
            $.ajax({
                type: "POST",
                data: {data: JSON.stringify(form_data)},
                success: function(res){
                    console.log(res);
                }
            });
        });
    </script>
    
    <?php } ?>
    

    【讨论】:

    • 尽可能多地工作,但我真的不喜欢尽可能多地将 PHP 和 HTML 放在同一个文件中。更喜欢 MVC 的概念——即使它不是 MVC(例如,保持模型、视图和控制器完全分开)
    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    相关资源
    最近更新 更多