I'm attempting to send a JSON document to a PHP script using AJAX. The JSON document is constructed from the value of a <textarea>.
I have successfully executed the solution using JQuery, and (for fun?!) am working on achieving the same result with vanilla AJAX.
The calling PHP script:
<script>
function preview() {
var xhttp;
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("output").innerHTML = this.responseText;
}
};
var postData = {
'html' : document.getElementById("editor").value,
};
xhttp.open("POST", "markuppreview.php");
xhttp.setRequestHeader('Content-type', 'application/json');
xhttp.send(postData);
};
</script>
<pre><textarea id="editor" name="content" placeholder="Enter your markup"></textarea></pre><br />
<button value="Preview" onclick="preview();">Preview</button>
<h2>Preview</h2>
<div id="output" style="height:100px"></div>
The receiving PHP:
$Parsedown = new Parsedown();
$Parsedown->setSafeMode(true);
$data['success'] = false;
$data['output'] = '';
if ($_POST['html']) {
$data['success'] = true;
$data['output'] = $Parsedown->text($_POST['html']);
}
echo json_encode($data);
I receive the following error, and can't work out why the postData.html isn't being received.
Warning: Undefined array key "html" in /Library/WebServer/Documents/markuppreview.php on line 8
{"success":false,"output":""}
I also tried a Javascript object method for constructing the JSON document, but received the same message. When I alert the JSON document, it does show an html element with the data from the <textarea>.
var postData = new Object();
postData.html = document.getElementById("editor").value;
postData = JSON.stringify(postData);
alert(postData);
CodePudding user response:
Because you're attempting to send JSON-formatted data and $_POST works with form data, not a JSON payload.
You'll need to do
$json = json_decode(file_get_contents('php://input'));
to read the POST input as a raw string, then JSON decode it.
Also, please use fetch() instead of the (pretty legacy) XMLHTTPRequest API.
CodePudding user response:
There are multiple problems coming together here:
You seem to attempt to send JSON (according to your
Content-Type: application/jsonheader), yet PHP natively only supports form data (query string or multipart). If you want to use JSON, then you have to access the raw body withfile_get_contents('php://input')and usejson_decodeon it to get an object (instead of using the associative array superglobal$_POST).You don't actually send anything useful, because you are passing an object to
XMLHttpRequest#sendwhich will get coerced to a string and end up as just[object Object]. If you do want to send JSON, you'll have to applyJSON.stringifyon the data first and send the result.
Going from here, you can either change both client and server to fully use JSON or update the client to send form data.
However, I would recommend to switch to a more modern (and easy-to-use) solution than XMLHttpRequest anyway, ideally fetch. With the existing server code (using form data), the following client code would work:
async function preview () {
const response = await fetch('markuppreview.php', {
method: 'POST',
body: new URLSearchParams({ html: document.getElementById("editor").value })
})
document.getElementById('output').innerHTML = await response.text()
}
