36

I am trying to use fetch() API POST method in order to grab the POST data in PHP.

Here is what I have tried:

var x = "hello";
fetch(url,{method:'post',body:x}).then(function(response){
    return response.json();
});

PHP:

<?php
if(isset($_GET['x']))
{
    $get = $_GET['x'];
    echo $get;
}
?>

Is this correct?

7 Answers 7

60

It depends:

If you want to $_GET['x'], you need to send the data in the querystring:

var url = '/your/url?x=hello';

fetch(url)
.then(function (response) {
  return response.text();
})
.then(function (body) {
  console.log(body);
});

If you want to $_POST['x'], you need to send the data as FormData:

var url = '/your/url';
var formData = new FormData();
formData.append('x', 'hello');

fetch(url, { method: 'POST', body: formData })
.then(function (response) {
  return response.text();
})
.then(function (body) {
  console.log(body);
});
Sign up to request clarification or add additional context in comments.

6 Comments

Hi, Sorry this is over two years old reply, but why does the POST have to be in formData ? When using ajax, we don't have to declare this when POSTing.
@kkmoslehpour Sorry this is an over two years old reply, but the fetch POST uses formData as its means of structuring non-JSON-encoded POST data - Ajax is a quite different means of POSTing and so has a different way of structuring itsPOSTed data
In short: var formData = new FormData(); formData.append('x', 'hello'); fetch("/url/post", {method: 'POST', body: formData}).then(r => r.text()).then(body => console.log(body));
Regarding the comments about POST using FormData, it concerns how the PHP $_POST variable works. It expects the data in that format. If you're using JSON for the body, see the answer from Rafael.
Not necessarly a FormData, a body: JSON.stringify({}) works as well
|
39

Apparently, when using the Fetch API to send data to a PHP server, you'll have to handle the request a little different from what you're used to.

The data you're "POSTing" or "GETting" is not going to be available in the super global variables since this input is not coming from a multipart-data form or an application/x-www-form-urlencoded

You can get your data by reading the special file: php://input, for example using file_get_contents('php://input') and then try to decode that input with json_decode().

You can read more about it here:

https://codepen.io/dericksozo/post/fetch-api-json-php

4 Comments

This works but the server implementation is hacky. I recommend looking at the answer below and post with a FormData object instead.
I was looking for this. Thank you! It solved my problem. Now, in the server side, how would you access each bit... say the data is a form that has "address", "name", "city", etc... how do you access each object?
This is actually the answer to the question, and not "restructure everything else you are doing so you can get it on _POST" answer. Especially when dealing with a REST setup where you are passing json, and not Form Data.
In my case, it shows NULL when I use var_dump(file_get_contents("php://input"));
16

In vanilla JS I use the postData function from MDN:

/**
 * send_body___receive_response.js
 *
 * Can of-course be in <script> tags in HTML or PHP
 */

async function postData( url='', data={ } ) {
  // *starred options in comments are default values
  const response = await fetch(
    url,
    {
      method: "POST", // *GET, POST, PUT, DELETE, etc.
      mode: "same-origin", // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin", // include, *same-origin, omit
      headers: {
        "Content-Type": "application/json",  // sent request
        "Accept":       "application/json"   // expected data sent back
      },
      redirect: 'follow', // manual, *follow, error
      referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      body: JSON.stringify( data ), // body data type must match "Content-Type" header
    },
  );

  return response.json( ); // parses JSON response into native JavaScript objects
}

const data = {
  'key1': 'value1',
  'key2': 2
};

postData( 'receive_body___send_response.php', data )
  .then( response => {
    // Manipulate response here
    console.log( "response: ", response ); // JSON data parsed by `data.json()` call
    // In this case where I send entire $decoded from PHP you could arbitrarily use this
    console.log( "response.data: ", JSON.parse( response.data ) );
  } );

You could just POST data but I like to receive a response that it was successful.

/**
 * receive_body___send_response.php
 */

/* Get content type */
$contentType = trim($_SERVER["CONTENT_TYPE"] ?? ''); // PHP 8+
// Otherwise:
// $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';

/* Send error to Fetch API, if unexpected content type */
if ($contentType !== "application/json")
  die(json_encode([
    'value' => 0,
    'error' => 'Content-Type is not set as "application/json"',
    'data' => null,
  ]));

/* Receive the RAW post data. */
$content = trim(file_get_contents("php://input"));

/* $decoded can be used the same as you would use $_POST in $.ajax */
$decoded = json_decode($content, true);

/* Send error to Fetch API, if JSON is broken */
if(! is_array($decoded))
  die(json_encode([
    'value' => 0,
    'error' => 'Received JSON is improperly formatted',
    'data' => null,
  ]));

/* NOTE: For some reason I had to add the next line as well at times, but it hadn't happen for a while now. Not sure what went on */
// $decoded = json_decode($decoded, true);

/* Do something with received data and include it in response */
// dumb e.g.
$response = $decoded['key2'] + 1; // 3

/* Perhaps database manipulation here? */
// query, etc.

/* Send success to fetch API */
die(json_encode([
  'value' => 1,
  'error' => null,
  'data' => null, // or ?array of data ($response) you wish to send back to JS
]));

5 Comments

Thank you @GillesBossuyt for reminding me to refactor my code in SO too! :) Just edited ;) Am I wrong, thinking there was an error before in if (! ...) with the unnecessary exclamation mark?
Yes, I regarded it as a typo ;)
Thanks for replying. To others: The bug has been fixed.
there is body: JSON.stringify( data ) and again postData( .., JSON.stringify( data ) ) will do : JSON.stringify( JSON.stringify( data ) ) correct ?
@MisterJojo Indeed, thank you. Fixed
5

Remember $_POST in PHP only grabs either formData() or urlSearchParams() data and for other all types of data especially data from the importing from other files or external api data, you must follow the steps. Steps:

  1. Use file_get_contents(php://input) to receive the data in php
  2. Decode it using json_decode($data) and finally after reading/writing to the database
  3. Send the response using json_encode($response).

It's Easy :-))

Comments

5

If it happens that you need to work with an existent server, that it's coded with $_POST and expect parameters from a normal form, NOT ENCODED AS JSON, you can use the formdata, that's exatctly to simulate a form.

let fd = new FormData();
fd.append("var1", val)
fd.append("var2", "Hello World");
fetch('/servers/server.php', {method: "POST", body: fd})

In this way, your server will receive POSTed fields as they were from a normal form input field.

$var1 = $_POST['var1']; $var2 = $_POST['var2'];

Comments

3

you can build the body "foo=bar&blah=1" from a json { foo: "bar", "blah": 1}

async function json_as_post_data() {
  let data = {
    foo: "bar",
    "blah": 1
  }
  return fetch('url-here', {
    method: 'post',
    headers: { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" },
    body: Object.entries(data).map(([k, v]) => { return k + '=' + v }).join('&') // 'foo=bar&blah=1'
  }).then(response => {
    return response.json();
  });
}
console.log(await json_as_post_data());
echo json_encode($_POST);

Comments

2

Working example that show how to add two numbers with fetch api using FormData.

For each operation you better have different FormData with its own fields.

HTML:

<html>
<head></head>

<body>

<div id="numbers_addition">
    <input type="text" id="num1" placeholder="First Number">
    <input type="text" id="num2" placeholder="Second Number">
    <button type="button" onclick="addMyNumbers()">Add</button>
    <p id="result"></p>
</div>

<script id="script_add">

    function addMyNumbers()
    {
        let num1=document.getElementById("num1").value;
        let num2=document.getElementById("num2").value;
        opAddNumbers(num1, num2);
    }

    const frmAddNumbers = new FormData(); // create single instance
    frmAddNumbers.set('cmd', "add_numbers"); // this cmd will not change
    frmAddNumbers.set('first_number', "");
    frmAddNumbers.set('second_number', "");

    function opAddNumbers(num1, num2) {
        frmAddNumbers.set('first_number', num1);
        frmAddNumbers.set('second_number', num2);

        fetch('./cmd.inc.php', {method: 'POST', body: frmAddNumbers})
        .then(res => res.json()) // res.text()
        .then(res => displayResult(res))
        .catch(e => console.error('Error, opAddNumbers(), ' + e))
    }

    function displayResult(response)
    {
        console.log(response);
        document.getElementById("result").innerHTML = `Result = ${response["result"]}`;
    }

</script>

</body>
</html>

PHP ('cmd.inc.php'):

<?php

$cmd=$_POST['cmd'];

switch ($cmd) {
    case "add_numbers":
        $num1=$_POST['first_number'];
        $num2=$_POST['second_number'];
        $result = array("result" => $num1 + $num2);
        $output = json_encode($result);
      break;
  }

echo $output;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.