Reputation: 111
I am trying to send JSON data using XMLHttpRequest in WordPress:
document.getElementById("user_vote").addEventListener("click", function(event) {
event.preventDefault();
//action to handle in WP add_action("wp_ajax_my_user_vote", "my_user_vote");
let action = "my_user_vote";
let url = myAjax.ajaxurl;
let data = {
action: action,
post_id : this.dataset.post_id,
nonce: this.dataset.nonce
};
let json = JSON.stringify(data);
let xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.onreadystatechange = function() {
if (this.readyState != 4) return;
document.getElementById('response').innerHTML = this.responseText;
}
xhr.send(json);
});
When I am setting headers to JSON xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
I am getting empty $_REQUEST
variable. It seems that WP do not understanding this headers or I am doing something wrong.
I saw this post. When I am checking $input = file_get_contents('php://input');
in admin-ajax.php
it returning string of my data: {"action":"my_user_vote","post_id":"1","nonce":"2b2eaea6d3"}
but $_REQUEST
variable is empty.
All working good with this headers xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
but I want to send JSON.
Why using jQuery.ajax I can simple send JSON data to admin-ajax.php
and cant do it with javascript?
Add 1
Here are the right way to send AJAX in WP:
jQuery.ajax({
type : "post",
dataType : "json",
url : myAjax.ajaxurl,
data : {action: "my_user_vote", post_id : post_id, nonce: nonce},
success: function(response) {
//do stuff
}
})
You mean that in this case jQuery will not set headers to application/json
but will set them to application/x-www-form-urlencoded
and all this request will be produced to simple XMLHttpRequest
with standard headers and xhr.send(data)
converted to string, something like this "action=my_user_vote&post_id=1&nonce=2b2eaea6d3"
?
And I do not need to set headers to application/json
and use simple POST
request with standard headers?
Upvotes: 1
Views: 2131
Reputation: 943635
PHP will not automatically decode JSON and put it in $_POST
or $_REQUEST
.
As you have already discovered, you need to read the raw HTTP request body from STDIN and parse it explicitly to read a JSON formatted request in PHP.
Your problem appears to be a misunderstanding of what jQuery does. Probably when you are using jQuery you are doing something like this:
var data = { some: "object" };
jQuery.ajax({
url: "foo",
data: data,
method: "POST"
});
When you do that, jQuery will URL Encode the data
object. It will not JSON encode it.
Remember, while JSON syntax is inspired by JavaScript literal syntax, the results of having an object literal in JavaScript source code will give you an object and not a string of JSON.
If you were using jQuery to make a JSON formatted request you would need something like this:
jQuery.ajax({
url: "foo",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
method: "POST"
});
To encode your object as form data with XHR, you would want something along the lines of:
var data = { some: "object" };
var array = [];
Object.keys(data).forEach(element =>
array.push(
encodeURIComponent(element) + "=" + encodeURIComponent(data[element])
)
);
var body = array.join("&");
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(body);
Upvotes: 4