Background:
The following AJAX
code works successfully (ReactJS + JQuery frontend, PHP backend
).
const data = {request_type:"load_data", start:1, end:50};
$.ajax({
type: "POST",
url: "http://localhost/site/server.php",
data: data,
dataType: "json",
success: (JSobject) => {
this.setState({arr: JSobject.arr});
}
});
In Chrome Dev Tools server.php
's Headers show up as "Form Data
" like so:
At the PHP server backend, there's this line of code:
$request_type = $_POST["request_type"];
In an attempt to learn how to do Fetch (I've avoided it so far mostly because I had AJAX boilerplate that worked well), I've been playing around with trying to build a drop-in replacement for the above code.
I tried this:
const data = {request_type:"load_data", start:1, end:50};
fetch("http://localhost/site/server.php", {
method: "POST",
body: data
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
But I get this PHP error:
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php
's Headers show up like so:
So, I tried changing the data to JSON.stringify(data) like so:
const data = {request_type:"load_data", start:1, end:50};
fetch("http://localhost/site/server.php", {
method: "POST",
body: JSON.stringify(data)
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
But I still get the exact same PHP error:
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php
's Headers show up like so:
Out of general frustration (although it's pointless because I'd be still using JQuery), I thought I'd use JQuery's $.param()
, and that would surely work.
So I tried this:
const data = $.param({request_type:"load_data", start:1, end:50});
fetch("http://localhost/site/server.php", {
method: "POST",
body: data
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
Still get the same PHP error
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php
's Headers show up like so:
My question: how do I modify the Fetch
code above so that it becomes a drop-in replacement for the AJAX
code up top.
I realize that the use of horizontal lines can be bothersome for some. You can give yourself permission to believe that it really helps a lot of us regular folks follow what's going on in the question.
Answering my own question for others who might encounter this issue in future (and also for my own reference). Figured out the answer via this link and this link. The following code worked:
fetch("http://localhost/site/server.php", {
method: "POST",
body: JSON.stringify(data)
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
I had to change some PHP code on the server. The initial "gatekeeper" code was:
$_POST = array_map("trim", $_POST);
$request_type = $_POST["request_type"];
This had to be commented out:
$_POST = array_map("trim", $_POST); //this had to be commented out
And this had to be added instead:
$content = trim(file_get_contents("php://input"));
$_POST = json_decode($content, true);
And in Chrome Dev Tools server.php
's Headers show up as "Request Payload
":
I also saw some suggestions to add a "headers
" key like so:
fetch("http://localhost/site/server.php", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded",},
body: JSON.stringify(data)
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
This did also work, but in Chrome Dev Tools server.php
's Headers show up as "Form Data
":
Another way to do this is by wrapping the object (to be sent) in JQuery's $.param()
(I was interested in this because I often use $.param()
to append key-values to form.serialize()
, on the client side before sending to the PHP on the server)
const data = $.param({request_type:"load_data", start:1, end:50});
fetch("http://localhost/site/server.php", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded",},
body: data
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
The advantage of doing it this way was that no changes were needed to the code on the server side.
In Chrome Dev Tools server.php
's Headers show up as"Form Data
":
Without using JQuery:
Re: the previous method (using $.param()
), it's possible to do it completely without JQuery
, but then one would need some function to chain the javascript object's key-value pairs while properly encoding special characters as x-www-form-urlencoded (this link explains how to do it).
E.g., instead of this:
const data = $.param({request_type:"load_data", start:1, end:50});
...
body: data
One would do this:
const data = {request_type:"load_data", start:1, end:50};
...
...
body: "request_type=load_data&start=1&end=50"