I'm trying to post (as in request type of POST) some JSON data to a PHP back end page using Fetch, but for some reason, the PHP page is reading the POST as empty.
Form Markup
<form action="add_to_mailchimp.php" method="POST">
<input type="text" name="email" placeholder="Enter your email" />
<button type="submit">Go</button>
</form>
Javascript:
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const payload = {
// email: document.querySelector('[name="email"]').value,
email: '[email protected]', // hard code value just for example
};
console.log('about to submit %o', payload);
fetch('add_to_mailchimp.php', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
console.log(response);
return response.json();
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
});
});
PHP
<?php
print json_encode(array('postObj' => $_POST, 'reqType' => $_SERVER['REQUEST_METHOD'));
die;
?>
The following is written to the console upon submitting the form.
{postObj: [], reqType: "POST", [[Prototype]]: Object}
When I remove the javascript and allow the form to submit normally and add the following to the PHP:
print '<pre>';
print_r($_POST);
print '</pre>';
I get:
Array
(
[email] => [email protected]
)
Where [email protected]
is whatever value is entered into the text field. I've been banging my head into the wall trying to figure this out for the past hour and am officially out of ideas. Can anyone shed some light on this for me? Thanks!
CodePudding user response:
Change your PHP to the code below:
$json = file_get_contents('php://input');
print_r($json);
This allows you to read raw data from the request body
CodePudding user response:
A single page, working demo to illustrate how you might accomplish the stated aims. Using, as already pointed out, file_get_contents('php://input')
is correct as you are no longer sending a regular www-urlencoded
or form-data
type request as you specify the Content-Type
to be json
Also added in a small piece of code to clear the input element on focus and restore if the user failed to add an email address of their own - very rudimentary though with a regex to check that any entered value is more or less correct as an email address. Further checks server-side should be done using filter_input
or similar to ensure email is actually valid when received at server.
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' ){
$json=json_encode(
array(
'postObj' => file_get_contents('php://input'),
'reqType' => $_SERVER['REQUEST_METHOD']
)
);
exit( $json );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Mailchimp</title>
</head>
<body>
<form name='mailchimp' action='add_to_mailchimp.php' method='POST'>
<input type='text' name='email' placeholder='Enter your email' value='[email protected]' />
<button type='submit'>Go</button>
</form>
<script>
const b=false; // set as true to change url used by Fetch
const d=document;
const f=d.forms.mailchimp;
const pttn=/^[^\s@] @[^\s@] \.[^\s@] $/;
d.addEventListener('DOMContentLoaded', () => {
// clear default value on focus
f.email.addEventListener('focus',e=>{
e.target.value='';
});
// restore default value if left empty
f.email.addEventListener('blur',e=>{
if( !e.target.value.match( pttn ))alert('Invalid email address');
if( e.target.value=='' )e.target.value=e.target.defaultValue;
});
// send ajax request
f.addEventListener('submit', e=>{
e.preventDefault();
if( !f.email.value.match( pttn ) ) return
const payload = {
email:f.email.value
};
const args={
method:'POST',
mode:'cors',
body:JSON.stringify( payload ),
headers:{
'Content-Type':'application/json',
}
};
const callback=(r)=>{
console.log( r );
};
// Change the variable above to true to use Form Action as target url
let url=b ? f.action : location.href;
fetch( url, args )
.then(r=>r.json())
.then(callback)
.catch(console.log)
});
});
</script>
</body>
</html>