I’m trying to pass a FormData inside a JSON array to an AJAX script:
$('#form').submit(function(e) { e.preventDefault(); let formData = new FormData(this), data = {'action': 'insert', 'data': formData}; $.ajax({ data: data, url: '/wp-content/plugins/eng-dealer-map/bin/Admin.php', type: 'post', cache: false, contentType: false, processData: false, success: function(res) {console.log(res)}, error: function(res) {console.log(res)} }) });
Then /bin/Admin.php
<?php ini_set('display_errors',1); ini_set('display_startup_errors',1); error_reporting(-1); $ds = DIRECTORY_SEPARATOR; require_once $_SERVER['DOCUMENT_ROOT']. $ds. 'wp-content'. $ds. 'plugins'. $ds. 'eng-dealer-map'. $ds. 'vendor'. $ds. 'autoload.php'; var_dump($_POST); $admin = new AppEndpointAdmin(['action' => $_POST['action'], 'data' => $_POST['data']]); echo $admin->execute();
Which, in turn, finally goes to this (minified) class:
<?php namespace AppEndpoint; class Admin { protected $db; protected $table; protected $sql; protected $data; public function __construct($foo) { require_once $_SERVER['DOCUMENT_ROOT']. DIRECTORY_SEPARATOR. 'wp-config.php'; global $wpdb; $this->db = $wpdb; $this->table = '`'. $this->db->prefix .'trey_is_the_best`'; $this->sql = $this->build($foo['action']); $this->data = $foo['data']; } public function build(string $action) { switch($action) { case 'insert': return $this->insertSql(); break; case 'update': return $this->updateSql(); break; case 'remove': return $this->removeSql(); break; default: throw new Exception('trey'); break; } } public function execute() { if (!empty($this->sql)) { try { if ($this->db->query($this->db->prepare($this->sql, $this->data))) { return true; } else { throw new Exception($this->db->last_error); } } catch (Exception $e) { throw new Exception($e->getMessage()); } } else { return 'SQL empty!'; } } }
Unfortunately, it seems $_POST
gets lost along the way. Adding this in my JS:
for (let pair of formData.entries()) { console.log(pair[0]+ ', ' + pair[1]); }
which shows my data correctly. I then var_dump($_POST)
in bin/Admin.php
which shows an empty array.
I changed 'data': formData
to 'data': 'hello, world'
so I have a feeling FormData doesn’t like being inside a JSON array with other elements?
So how do I send FormData with other elements to my AJAX script? I know I could use:
formData.append('action', 'action-value')
but that feels like it’s an extra step when it could just been sent as one object to my script.
I also tried using JSON.stringify
on formData
but again, nothing. Is there a way I can send formData alongside other data as one object without using .append()
? Or is that my only option?
Advertisement
Answer
I have a feeling FormData doesn’t like being inside a JSON array with other elements?
Correct. You can’t convert FormData to JSON.
So how do I send FormData with other elements to my AJAX script?
Add the extra data to the FormData.
I know I could use:
formData.append('action', 'action-value')
Yes, do that.
but that feels like it’s an extra step when it could just been sent as one object to my script.
The FormData
object is one object. You just need to add the data to it instead of adding the data to a different object and then trying to add the data from FormData
to it.