通过fetch API和 XHR的同步POST请求发送给PHP的 JavaScript变量,在服务器端的POST参数中不会包含它们
我的目标是让用户能够在一个表单中提交数据,随后这些数据可以在PHP中被处理和修改,输出可以在不刷新页面的情况下显示。我已经在JavaScript中发现了两种同步的POST方法:fetch和 XHR。
当我在表单中输入内容,然后按提交按钮时,会有响应,但变量并未成功传递给PHP。我用print_r($_POST); 来测试变量是否已传递,输出总是 "Array ( )",意味着没有POST变量。使用alert() 和console.log() 函数,我可以看到PHP文件已成功被联系,但为什么在POST下 PHP中看不到这些变量?
我尝试发送FormData对象、JSON字符串、普通字符串,但都没有发出POST。我知道可以用JSON将变量从PHP传给JS,并在JS中改变页面,但我惊讶地发现按下按钮后, PHP脚本中的字符串没有回显到页面。有人能解释原因吗?
我试过这个帖子的一些答案中的方法,但都没有对我起作用。我把 action= 和 method= 的参数改为空字符串,我同时使用了 <button></button> 与 <input type="button"> 标签,我也尝试过 使用jQuery——也许这是WordPress的问题——而 警报响应 能成功生成响应,但它没有包含我打算传给PHP的 JS变量。使用 return false; 也没有帮助。
以下是代码:
<html>
<div>
<section>
<form id="testForm" action="file.php" method="post">
<input type="text" id="testInput" name="testInput">
<input type="button" id="testBtn" name="testBtn" value="Test Button">
</form>
</section>
</div>
</html>
<?php
echo "This works!"; //this is visible in alert or console but never the page
print_r($_POST); // always returns an empty array so far
?>
<script>
let testButton = document.getElementById("testBtn");
let tef = document.getElementById("testForm");
var variableValue = tef.value;
var formData = new FormData(tef);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/file.php", true);
xhr.open("GET", "/file.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error("Error:", xhr.status);
}
}
};
testButton.onclick = function(){
testButton.style.color = "red"; // confirm click
fetch("/file.php", {
method: "POST",
body: JSON.stringify({'testForm':variableValue})
})
.then(res => res.text())
.then(txt => {
alert(txt);
})
.catch(e => console.error(e));
xhr.send(formData);
xhr.onload = function(){
testButton.style.color = "purple"; // initial confirmation XHR method has worked
};
}
</script>
解决方案
请求方法被覆盖导致的问题。
原先有:
xhr.open("POST", "/file.php", true);
xhr.open("GET", "/file.php", true);
第二次 open() 调用覆盖了第一次,因此实际发送的请求是 GET,而不是 POST。
这就是为什么:
print_r($_POST);
总是返回:
Array ( )
因为 $_POST 只包含来自POST请求的数据。
去掉第二行之后,表单数据就正确工作:
let formData = new FormData(document.getElementById("testForm"));
let xhr = new XMLHttpRequest();
xhr.open("POST", "file.php", true);
xhr.onload = function () {
console.log(xhr.responseText);
};
xhr.send(formData);
PHP:
<?php
echo "This works!<br>";
print_r($_POST);
?>
调试时我还学到的另一点:
如果使用:
JSON.stringify(...)
配合 fetch(),PHP将不会自动填充 $_POST。
对于JSON请求,数据必须像下面这样读取:
$data = json_decode(file_get_contents("php://input"), true);
另外,404 Not Found 的错误是由于使用了错误的路径:
/file.php
它指向服务器根目录。
使用:
file.php
或正确的项目路径就解决了这个问题。
Here is the final working code :
<html>
<body>
<div>
<section>
<form id="testForm">
<input type="text" id="testInput" name="testInput">
<input type="button" id="testBtn" value="Test Button">
</form>
</section>
</div>
<script>
let testButton = document.getElementById("testBtn");
let tef = document.getElementById("testForm");
testButton.onclick = function () {
testButton.style.color = "red";
var formData = new FormData(tef);
var xhr = new XMLHttpRequest();
xhr.open("POST", "file.php", true);
xhr.onload = function () {
if (xhr.status == 200) {
alert(xhr.responseText);
testButton.style.color = "purple";
} else {
console.log("Error");
}
};
xhr.send(formData);
};
</script>
</body>
</html>