使用原版 AJAX(不是 JQuery)将 JSON 文档发送到 PHP 脚本

Send JSON document to PHP script using vanilla AJAX (not JQuery)

我正在尝试使用 AJAX 将 JSON 文档发送到 PHP 脚本。 JSON 文档是根据 <textarea>.

的值构建的

我已经使用 JQuery 成功执行了该解决方案,并且(为了好玩?!)正在努力使用 vanilla AJAX.

实现相同的结果

调用PHP脚本:

<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>

正在接收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);

我收到以下错误,无法弄清楚为什么没有收到 postData.html。

Warning: Undefined array key "html" in /Library/WebServer/Documents/markuppreview.php on line 8
{"success":false,"output":""}

我还尝试了 Javascript 对象方法来构建 JSON 文档,但收到了相同的消息。当我 alert JSON 文档时,它确实显示了一个 html 元素,其中包含来自 <textarea>.

的数据
    var postData = new Object();
    postData.html = document.getElementById("editor").value;
    postData = JSON.stringify(postData);
    alert(postData);

因为您正在尝试发送 JSON-formatted 数据并且 $_POST 使用表单数据,而不是 JSON 负载。

你需要做

$json = json_decode(file_get_contents('php://input'));

将 POST 输入读取为原始字符串,然后 JSON 对其进行解码。

此外,请使用 fetch() 而不是(漂亮的传统)XMLHTTPRequest API。

这里有多个问题:

  1. 你似乎试图发送JSON(根据你的Content-Type: application/jsonheader),但PHP本身只支持表单数据(查询字符串或多部分)。如果您想使用 JSON,那么您必须使用 file_get_contents('php://input') 访问原始 body 并在其上使用 json_decode 以获得 object(而不是使用关联数组超全局 $_POST).

  2. 你实际上并没有发送任何有用的东西,因为你将一个 object 传递给 XMLHttpRequest#send ,它将被强制转换为一个字符串并最终只是 [object Object].如果您确实要发送 JSON,则必须先对数据应用 JSON.stringify 并发送结果。

从这里开始,您可以同时更改客户端和服务器以充分利用 JSON 或更新客户端以发送表单数据。

但是,无论如何,我建议切换到比 XMLHttpRequest 更现代(和 easy-to-use)的解决方案,最好是 fetch。使用现有的服务器代码(使用表单数据),以下客户端代码可以工作:

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()
}

如果您打算仅显示来自服务器的 return JSON object 的 output 属性,并且仅当 success 是真的,那么你需要使用它来代替上面的 await response.text() 行:

  const { success, output } = await response.json()
  if (success) document.getElementById('output').innerHTML = output

根据@CherryDT 的建议最终解决方案。

正在调用 PHP 脚本:

<script>
async function preview () {
    const response = await fetch('markuppreview.php', {
          method: 'POST',
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
          body: new URLSearchParams({ html: document.getElementById("editor").value })
    })
    const { success, output } = await response.json()
    if (success) document.getElementById('output').innerHTML = output
}
</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>

接收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);