Home > Software engineering >  Javascript: Issues with POST request via Fetch
Javascript: Issues with POST request via Fetch

Time:01-16

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