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://$$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 -'
$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.

Using a motion sensor on a Raspberry Pi with PHP

Adding a motion sensor to a Raspberry Pi is easy. In this article I’ll show you how to use it with PHP.

The HC-SR501 is a pyroelectric infrared PIR motion sensor module, that connects to the Raspberry Pi using just 3 wires.

Connect GND to GND on the Pi, VCC to +5V on the Pi, and OUT to GPIO 17 on the Pi. That’s all that’s needed.

Added a HC-SR501 motion detector to a Raspberry Pi

To use the sensor with PHP we use the PHPi library. This library supports event driven bindings for the Raspberry Pi GPIO. We install this using Composer.

composer require calcinai/phpi

To use the PHPi library we need to bring it in using the autoloader, and add some namespace shortcuts.

require 'vendor/autoload.php';

use Calcinai\PHPi\Pin;
use Calcinai\PHPi\Pin\PinFunction;

We then create a board

$board = \Calcinai\PHPi\Factory::create();

We now need to declare that we’re using GPIO pin 17 for input.

$pin = $board->getPin(17)

As this is event driven programming, we need to listen to the pin to see when it changes. When the pin goes high, we know motion has been detected and we can do something. In this example, we’ll just write a message to the screen.

$pin->on('level.high', function() {
        echo "Motion detected\n";

Finally we start the start the loop running, so the script is listening and reacting to events.


Putting it all together

Here’s the final working PHP to detect motion using the HC-SR501


require 'vendor/autoload.php';

use Calcinai\PHPi\Pin;
use Calcinai\PHPi\Pin\PinFunction;

$board = \Calcinai\PHPi\Factory::create();

$pin = $board->getPin(17) //BCM pin number

$pin->on('level.high', function() {
        echo "Motion detected\n";


Reading a temperature sensor using PHP on a Raspberry Pi

It’s easy to add a temperature sensor to a Raspberry Pi. In this example I’ll explain how to set it up and access the data using PHP.

The DS18b20 is a great digital temperature sensor. It only needs three wires and a resistor to get it working on the Raspberry Pi.

The red wire is +3.3v, the black is ground, and yellow is data.

The resistor is connected between red and yellow to pull up the voltage on the data line.

Red is connected to pin 1 on the GPIO, black to pin 6, and yellow to pin 7.

Connecting a temperature sensor to a Raspberry Pi

Reading the temperature

Now the circuit is ready, we can access the data. We need to enable the relevant modules on the Raspberry Pi to do this.

modprobe w1-gpio
modprobe w1-therm

If we now look in the /sys/bus/w1/devices/ directory, we should see a directory starting with 28. This is where we can find the temperature data. Inside this directory is a file called w1_slave. This is the file we read get the data. When we read it, it actually asks the sensor for the data and return it. This means there is a slight delay before the data returns.

pi@Nowscreen:~ $ cat /sys/bus/w1/devices/28-031683a865ff/w1_slave
95 01 4b 46 7f ff 0c 10 65 : crc=65 YES
95 01 4b 46 7f ff 0c 10 65 t=25312

The temperature is the value t=25312. We divide this by 1000 to get the temperature of 25.312 degrees celcius.

Reading the temperature with PHP

The first thing we need to do is to find the directory where the w1_slave file is. We can use globbing to help here.

$base_dir = '/sys/bus/w1/devices/';
$device_folder = glob($base_dir . '28*')[0];
$device_file = $device_folder . '/w1_slave';

Now we need to read in the data. We can use the file method as this returns each line of the file in an array.

$data = file($device_file, FILE_IGNORE_NEW_LINES);

Now we extract the temperature. We check the first line is correct by checking for the value “YES” at the end of the line. If this is present we get the value for “t=” at the end of the second line. Finally we divide the value by 1000, and return it.

$temperature = null;
if (preg_match('/YES$/', $data[0])) {
    if (preg_match('/t=(\d+)$/', $data[1], $matches, PREG_OFFSET_CAPTURE)) {
        $temperature = $matches[1][0] / 1000;

Now we can display the temperature.

if ($temperature) {
    echo "Temperature is ${temperature}C\n";
} else {
    echo "Unable to get temperature\n";

Final PHP temperature sensor code

Here’s the finished code. I’ve also included two system calls to modprobe to ensure the necessary modules are loaded before reading.


exec('modprobe w1-gpio');
exec('modprobe w1-therm');

$base_dir = '/sys/bus/w1/devices/';
$device_folder = glob($base_dir . '28*')[0];
$device_file = $device_folder . '/w1_slave';

$data = file($device_file, FILE_IGNORE_NEW_LINES);

$temperature = null;
if (preg_match('/YES$/', $data[0])) {
    if (preg_match('/t=(\d+)$/', $data[1], $matches, PREG_OFFSET_CAPTURE)) {
        $temperature = $matches[1][0] / 1000;

if ($temperature) {
    echo "Temperature is ${temperature}C\n";
} else {
    echo "Unable to get temperature\n";

Controlling a LED on a Raspberry Pi with PHP

I wanted to make a LED light up using PHP on a Raspberry Pi. Most of the examples I’ve seen are for Python, so I wanted to see if was possible or not.

It is actually pretty easy to do, so I thought I’d share my work.

The first thing to do is to wire up the LED to the Raspberry Pi. I used a breadboard so there is no soldering required.

Connect the LED to GPIO pin 18, along with a 330ohm resistor, to GND. We need the resistor to limit the current through the LED otherwise it could burn out.

That’s the LED attached to Raspberry Pi, now we need to control it with PHP code.

PHP LED Control Code

Before we can write any PHP, we need to enable the gpio module on the Raspberry Pi.

sudo modprobe w1-gpio

We need a third party PHP library to be able to talk to the GPIO pins. I’m using php-gpio.

We need to install this with Composer before we can use it.

php composer.phar require ronanguilloux/php-gpio

We can now start our PHP code by using the autoloader to bring in the GPIO library.

require 'vendor/autoload.php';

use PhpGpio\Gpio;
$gpio = new GPIO();

Now to control the LED we need to make sure GPIO pin 18 is set to “out”.

$gpio->setup(18, 'out');

To turn the LED on we write the value “1” to pin 18.

$gpio->output(18, 1);

To turn the LED off we write the value “0” to pin 18.

$gpio->output(18, 0);

Finally, we need to make sure we clean up after ourselves.


The Final Code

Bringing this all together, we can write a simple PHP script to turn the LED on, wait 1 second, and turn it off again.


require 'vendor/autoload.php';

use PhpGpio\Gpio;
$gpio = new GPIO();
$gpio->setup(18, 'out');

echo "LED on\n";
$gpio->output(18, 1);


echo "LED off\n";
$gpio->output(18, 0);


The final code needs to be run as root to be able to access gpio.

Sparkline Creation Using PHP

Sparkline graphs have had a bit of press lately, so I’ve been playing about with generating them on my commutes to and from work.

If you’ve not heard of them before, a Sparkline is a small graph that is often used inline with text.

I’ve been using PHP, so I’ve created a simple class called Spark, with a single static method called line. This returns a simple string as an inline graph from an array of values that have been passed in.

Sparkline Examples

Here’s an example plotting a simple staircase type graph.


echo Spark::line(array(1, 2, 3, 4, 5, 6, 7, 8)) . "n";

> ▁▂▃▄▅▆▇█

Here’s an example plotting a cosine wave.

$cos = array();
for($i=0; $i <= 360; $i=$i+20) {
    $cos[] = cos($i * M_PI / 180);
echo Spark::line($cos) . "n";

> ██▇▆▅▄▃▂▁▁▁▂▃▄▅▆▇██


The code is available on GitHub as php-spark, and is free to use. It was inspired by a simple project for Go called Spark, which was inspired from elsewhere.

Fixing The National Rail Mobile Website For iPhones

I’ve been frustrated that the National Rail Enquiries mobile website doesn’t work properly on my Apple iPhone 4s, running iOS7, so I decided to take a look and see what is actually going on.

You can turn on debugging on your iPhone in the settings, so I turned this on, and loaded Safari on my Macbook Pro to take a look at what was actually happening.

The “Go” button on the mobile website acts as a submit button so I put a breakpoint on it to see what happened.

The event handler calls a function called setRecents, and it fails when it tries to save my recent stations to localStorage.

if (hasStorage) {
    localStorage.setItem("recentStations", recVal);
} else {
    setCookie("recentStations", recVal, 365);

The hasStorage global variable has a true value, allowing it to try to save to local storage, so I tried setting this to false and tried again. This time to website worked as it falls back to using cookies. So the problem is with localStorage on mobile Safari, I’m not sure why.

I then took a look to see how hasStorage was set. It was being set in the following function.

function checkStorage() {
    // Feature detect + local reference
    var storage,
    try {
        uid = new Date;
        (storage = window.localStorage).setItem(uid, uid);
        fail = storage.getItem(uid) != uid;
        fail && (storage = false);
    } catch (e) {}
    if (storage) {
        hasStorage = true; //if localstorage available

I set breakpoints through the function, reloaded and single stepped what was happening in the debugger.

The uid was correctly set to a Date object with the current date and time. The next line was where the problem occured. storage was assigned as a Storage object, but the setItem method failed. This meant that the storage variable was set, but an exception was thrown. The exception handler does nothing, so the line after was executed. This sees that storage is available, but not that it didn’t work, so sets hasStorage incorrectly to true.

The fix would be to modify the exception handler to set storage to false instead of doing nothing.

If any developers of the National Rail website are reading this, please add this line so I can use your website to plan my train journeys again using my iPhone!

The National Rail mobile website on an iPhone

All information correct at time of writing and publishing. 20th April 2014.

Returning A 410 HTTP Status Code In Apache

I had an SEO requirement to return a 410 HTTP status code for any URL’s with /advanced-search/ in them.

The following snippet can be added to your Apache config to achieve this.

# Return a 410 for any URL's with advanced-search in
RewriteCond %{REQUEST_URI} /advanced-search/
RewriteRule ^.*$ - [G]

Here we’re looking in the URI for the words /advanced-search/ and if found, the RewriteRule below is activated.

The RewriteRule takes the URL, keeps it intact and sets the [G] flag. The [G] flag forces the server to return a 410 Gone status as it’s response.

If Apache sees a [G] flag, it returns immediately and no further rewrite rules are evaluated.

A 410 HTTP status code indicates that a resource was once available, but isn’t any more.

Vagrant Failing To Launch

I use Vagrant based virtual machines to develop on. These are great as you can create custom environments at will without affecting your main machine.

Today I had the following error while trying to bring up my development environment.

wks:Vagrant robertprice$ vagrant up devvm
[ccfs] VM already created. Booting if it's not already running...
[ccfs] Clearing any previously set forwarded ports...
[ccfs] Forwarding ports...
[ccfs] -- 22 => 2222 (adapter 1)
[ccfs] -- 80 => 4567 (adapter 1)
[ccfs] Creating shared folders metadata...
[ccfs] Clearing any previously set network interfaces...
There was an error executing the following command with VBoxManage:

["hostonlyif", "create"]

For more information on the failure, enable detailed logging with

This turned out to be an error with VirtualBox, the virtualisation environment Vagrant uses. The solution is to force a restart of VirtualBox.

sudo /Library/StartupItems/VirtualBox/VirtualBox restart

I hope this helps others experiencing the same problem.

Data URI’s – Using and Generating

A recent project of mine needed an image embedding into some HTML via JavaScript. Rather than use a separate image, I decided to embed it directly using a data URI.

An image in a data URI is the MIME type of the image and it’s content encoded with base64 into a string. This is great as it cuts down HTTP requests but does cause the initial page weight to increase and be difficult to update as each change means the image needs re-encoding. Modern browsers support data URI’s very well, but older browsers such as IE 7 and below won’t like it.

Examples Using A Data URI Encoded Image

HTML Example

Here’s how I can embed the image of a red cross into an HTML <img> tag.

<img src="data:image/gif;base64,R0lGODlhFAAUAJEAAP/9/fYQEPytrflWViH5BAAAAAAALAAAAAAUABQAQAJKhI+pGe09lnhBnEETfodatVHNh1BR+ZzH9LAOCYrVYpiAfWWJOxrC/5MASbyZT4d6AUIBlUYGoR1FsAXUuTN5YhxAEYbrpKRkQwEAOw==" alt="red cross" width="20" height="20" />

CSS Example

Here’s how I can embed the image of a red cross into background of an HTML element using CSS.

body { 
  background: url(data:image/gif;base64,R0lGODlhFAAUAJEAAP/9/fYQEPytrflWViH5BAAAAAAALAAAAAAUABQAQAJKhI+pGe09lnhBnEETfodatVHNh1BR+ZzH9LAOCYrVYpiAfWWJOxrC/5MASbyZT4d6AUIBlUYGoR1FsAXUuTN5YhxAEYbrpKRkQwEAOw==) no-repeat left center;

JavaScript Example

Here’s how I can add an image element with the red cross in to an HTML page using JavaScript.

var imagestring = "data:image/gif;base64,R0lGODlhFAAUAJEAAP/9/fYQEPytrflWViH5BAAAAAAALAAAAAAUABQAQAJKhI+pGe09lnhBnEETfodatVHNh1BR+ZzH9LAOCYrVYpiAfWWJOxrC/5MASbyZT4d6AUIBlUYGoR1FsAXUuTN5YhxAEYbrpKRkQwEAOw==";
var image = new Image();
image.src = imagestring;
image.onload = function() {

Encoding An Image To A Data URI

It’s easy to create the encoded image string using PHP as it comes with a Base64 encoder as part of the language. Automatically detecting the MIME type of an image is a bit harder, but we can use finfo_file with comes as an extension to PHP 5.3 and above to do this.

So assuming the filename of the image is in the variable $filename we can use the following code to get the mimetype, read the image and encode it to a data URI string.

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename);

$contents = file_get_contents($filename);
echo "data:" . $mimetype . ";base64," . base64_encode($contents);


We’ve seen it’s easy to embed encoded images into code. I have wrapped the encoding routine into a command line PHP script and placed it on GitHub as php-base64-encode so it’s easy to quickly generate data URI’s.

DOMElement Content Extraction In PHP

I was using PHP to parse an HTML document using the PHP DOM extension and got stuck on extracting the contents of an element.

The documentation doesn’t make it clear how to do this, until you look and see that a DOMElement inherits from DOMNode. In DOMNode, there is a nodeValue property that holds the content.

DOMElement Content Example

So if I had a HTML document already loaded into a variable $html, and I wanted to extract the value of an element with the ID of “example”, I could do something like this.

$doc = new DOMDocument()
$element = $doc->getElementById('example');
echo $element->nodeValue;

An Alternative

A DOMNode also has a textContent property that can be used. This will return all the text for the node and descendants, which may not always be what you are hoping for.