Skip to Content

Read JSON request data with PHP

Posted on 2 mins read

While working on an API project, I realised that I actually didn’t know how to receive JSON data in the request body with PHP. Turns out it’s really simple with php://stdin.

Most projects we work on with PHP rely on forms to receive data. That’s what the $_POST superglobal is for: it contains all information passed via HTTP POST when sending data with content type application/x-www-form-urlencoded or multipart/form-data.

But what if you use the application/json content type? Up until PHP 5.6 we could use the $HTTP_RAW_POST_DATA superglobal, but this has been deprecated. Instead we should use the php://input stream to read raw data from the request body.

Below is an example script. The comments explain what’s happening:

<?php
// Only allow POST requests
if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') {
  throw new Exception('Only POST requests are allowed');
}

// Make sure Content-Type is application/json 
$content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
if (stripos($content_type, 'application/json') === false) {
  throw new Exception('Content-Type must be application/json');
}

// Read the input stream
$body = file_get_contents("php://input");
 
// Decode the JSON object
$object = json_decode($body, true);
 
// Throw an exception if decoding failed
if (!is_array($object)) {
  throw new Exception('Failed to decode JSON object');
}

// Display the object
print_r($object);

Let’s give this a quick whirl. Save the example as script.php and start the standalone PHP server with php -S localhost:8080 script.php.

Now let’s send it a POST request containing JSON data using cURL:

curl -X POST \
  -d '{"foo": ["bar", "baz"]}' \
  -H "Content-Type: application/json" \
  http://localhost:8080

Your JSON object should be printed out:

Array
(
    [foo] => Array
        (
            [0] => bar
            [1] => baz
        )

)

Easy!