1

I'm building some form data, populating it with arrays, and sending it over POST, via:

let fd = new FormData();
for (section in this.data.choices) {
    let key = section+(this.data.choices[section] instanceof Array ? '[]' : '');
    fd.append(key, this.data.choices[section]);
}
fetch('?get=plan', {method: 'post', body: fd}) //...

Here's the structure of this.data.choices:

{
    "mode": "o7ew4xqybwt",
    "packages": [
        "wx2xv1cakbe"
    ],
    "usertypes": [
        "s"
    ],
    "subjects": [
        "bxn5g1igm4l",
        "u1osgpv37fl",
        "q2scwqb27k7",
        "fl9riri0wpr"
    ]
}

However on the receiving side, in PHP, the arrays are arriving flattened. print_r($_POST) gives:

Array
(
    [mode] => o7ew4xqybwt
    [packages] => Array
        (
            [0] => wx2xv1cakbe
        )
    [usertypes] => Array
        (
            [0] => s
        )
    [subjects] => Array
        (
            [0] => bxn5g1igm4l,u1osgpv37fl,q2scwqb27k7,fl9riri0wpr
        )
)

It's no doubt something simple I'm missing but any help would be appreciated.

Mitya
  • 33,629
  • 9
  • 60
  • 107
  • 1
    why not just send the data as JSON instead? Saves a lot of messing about, and avoids this structure translation error you've introduced. – ADyson Aug 19 '20 at 14:28
  • Do you mean send it as a single POST field as stringified JSON, and then decode it on the back end, rather than sending the fields separately? – Mitya Aug 19 '20 at 14:31
  • Yes exactly that. You'll find this useful: https://stackoverflow.com/questions/18866571/receive-json-post-with-php – ADyson Aug 19 '20 at 14:32
  • Fair enough. Happy to give you the rep if you post that up. Seems odd that this should be an issue, though - you shouldn't have to resort to single-field JSON, surely. – Mitya Aug 19 '20 at 14:32
  • I've posted it - see below. Not sure what you mean by "single-field" JSON though. The whole point of JSON is that it can represent a complex data structure with multiple fields. In many ways it's actually a much neater and better format then encoded form-data. – ADyson Aug 19 '20 at 14:36
  • @ADyson Sorry, I wasn't clear - I meant, sending a single post param, containing JSON, rather than sending separate params as I am currently. – Mitya Aug 19 '20 at 14:39

2 Answers2

2

I think you should just send the data as JSON instead. It saves a lot of messing about, and avoids this structure translation error you've introduced. Instead you can just stringify your JS object directly to JSON, and send that to server.

And then on the PHP side you can receive and decode it, and then use it like a regular object (see Receive JSON POST with PHP for guidance on how to correctly receive JSON from a POST request in PHP).

ADyson
  • 57,178
  • 14
  • 51
  • 63
2
fd.append(key, this.data.choices[section]);

Above line means adding a single value to the key regardless of [] or normal keys. You will have to loop through them to add them one by one as array values.

let fd = new FormData();
for (section in this.data.choices) {
    if(this.data.choices[section] instanceof Array){
        this.data.choices[section].forEach(value => fd.append(section + '[]', value));           
    }else{
        fd.append(section, this.data.choices[section]);    
    }    
}
fetch('?get=plan', {method: 'post', body: fd}) //

As an alternative, send the JSON as is with header Content-type:application/json.

nice_dev
  • 17,053
  • 2
  • 21
  • 35
  • In some cases, like when you work with AJAX in Wordpress, you are basically forced into using FormData objects. In that case, this solution worked flawlessly for me! – Drago96 Apr 12 '22 at 15:01