Using file_get_contents to PUT JSON data over HTTPS to a webservice

It’s possible to use PHP’s file_get_contents to PUT JSON data to a RESTful webservice if you don’t want to use cURL.

In this example I’m going to try to add or update a person using the NationBuilder API.

Firstly, we need the URL of the webservice, and the data you want to update as a JSON string.

$access_token = 'set access token here';
$nation = 'set nation name here';
$url = "https://$nation.nationbuilder.com/api/v1/people/push?access_token=$access_token";
// details we want to update
$data = [
    'person' => [
        'email_opt_in' => true,
        'do_not_contact' => false,
        'do_not_call' => false,
        'first_name' => 'Robert',
        'last_name' => 'Price',
        'email' => 'robert.price@email.adress',
        'home_address' => [
            'zip' => 'AB1 2CD'
        ],
        'bio' => 'Software developer - robertprice.co.uk'
    ]
];
$json_data = json_encode($data);

Now we need to setup a stream_context so file_get_contents knows how to handle the request.

Even though we’re PUTing data over HTTPS, we need to use the http context. We set method to PUTContent-type to application/json, Accept to application/json, Connection to close, and Content-length to the length of our JSON string. We’re PUTing this data over HTTP1.1 so we set the to 1.1. We’re sending the JSON in the body of the request, so we set this in the content.

As we are using HTTPS, we need to configure the ssl settings. In this case I’m not going to verify the peer or the peer name.

$context = stream_context_create([
    'http' => [
        'method' => 'PUT',
        'header' => "Content-type: application/json\r\n" .
                    "Accept: application/json\r\n" .
                    "Connection: close\r\n" .
                    "Content-length: " . strlen($json_data) . "\r\n",
        'protocol_version' => 1.1,
        'content' => $json_data
    ],
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);

Finally we PUT the data by calling file_get_contents. NationBuilder returns a JSON response to this call, so we can decode that and echo a confirmation message to the screen.

$rawdata = file_get_contents($url, false, $context);
if ($rawdata === false) {
    exit("Unable to update data at $url");
}
$data = json_decode($rawdata, true);
if (JSON_ERROR_NONE !== json_last_error()) {
    exit("Failed to parse json: " . json_last_error_msg());
}
echo "Updated details for {$data['person']['first_name']} {$data['person']['last_name']}\n";

The full code for this, and some other examples of querying NationBuilder using PHP, can be found in my NationBuilder People In Nation – GitHub repository.

You may also be interested in my previous article on POSTing JSON to Web Service.

POSTing JSON To A Web Service With PHP

I needed to POST JSON formatted data to a RESTful web service using PHP earlier, so I thought I’d share my solution.

There are a couple of approaches that could be taken, using the CURL extension, or file_get_contents and a http context. I took the later way.

When POSTing JSON to a RESTful web service we don’t send post fields or pretend to be a form, instead we have to send the JSON data in body of the request, and let the web service know it’s JSON data by setting the Content-type header to application/json.

$article = new stdClass();
$article->title = "An example article";
$article->summary = "An example of posting JSON encoded data to a web service";

$json_data = json_encode($article);

$post = file_get_contents('http://localhost/rest/articles',null,stream_context_create(array(
    'http' => array(
        'protocol_version' => 1.1,
        'user_agent'       => 'PHPExample',
        'method'           => 'POST',
        'header'           => "Content-type: application/json\r\n".
                              "Connection: close\r\n" .
                              "Content-length: " . strlen($json_data) . "\r\n",
        'content'          => $json_data,
    ),
)));

if ($post) {
    echo $post;
} else {
    echo "POST failed";
}

Here I’m first creating an example PHP stdClass object, populating it with some data, then serialising it to a JSON string. The real magic is using file_get_contents to POST it over HTTP to my test web service. If the POST succeeds, then it’s displayed, else an error message is shown.

It’s important to note I send the header, Connection: close . Without this, your script will hang until the web server closes the connection. If we include it, then as soon as the data has POSTed the connection is closed and control returned to the script.