Three Ways to Build Dynamic Web APIs using PHP

In this article, we learn how to build dynamic Web APIs using PHP. Why PHP? PHP is a very popular programming language used for rendering server-side web pages and is included as a standard option with many web hosting providers including HostGator (my provider). I had a need to generate simulated one-minute IoT data for a recent article I wrote on Fetching, Filtering, and Sorting JSON APIs in Google Sheets: The Missing Functions. Much to my surprise and delight, PHP is both powerful and fun, and I am here to share some of my learnings with you. Let's get started and highlight three ways to build dynamic Web APIs using PHP.

Article contents

What is Dynamic Web API?

For the purposes of this article, I define a dynamic web API as an application programming interface (API) that enables an application to "ask questions" through an HTTP request and receive answers via an HTTP response. The HTTP response in our context is transmitted using JSON but could also be XML or some other structured format.

My goal was to receive (simulated) real-time data for the water temperature in a fish tank in the following JSON format:

{
  "Tank": "Tank1",
  "watertemp": {
    "time": "2019-05-11 22:20 GMT",
    "value": 72.5
  }
}

The "time" and "value" JSON attributes need to update every minute to simulate real sensor readings.

How can we build a solution so our JSON dynamically updates when invoked via an HTTP request?

Creating a PHP Development Environment

I won't delve deeply into the intricacies of setting up a PHP development environment since there are other articles that explain this quite well. I will say, however, that it is helpful to create a PHP environment on your local system to build PHP scripts rather than creating PHP scripts in a text editor and sending them by FTP to your hosting provider and attempting to debug. Here are my general steps for creating a local PHP dev environment:

  • Install VirtualBox to run on VM Windows 10. (I could have also used a Raspberry Pi or other dedicated Linux box.)
  • Install Ubuntu on VirtualBox.
  • Create a shared folder using VirtualBox to share files between Ubuntu on VirtualBox and the Windows 10 host operating system.
  • Use Visual Studio Code on Windows to edit the PHP files in the shared folder. (I could have run VS Code on Ubuntu also.)
  • Install the popular PHP Intelephense VS Code extension to enable PHP intellisense and other features.
  • Install LAMP (Linux Apache MySQL PHP) stack on Ubuntu using this tutorial. MySQL was not needed in my current context, but I installed it anyway for potential use in future projects.

I also found it helpful to include the following lines at the top of my PHP file to show detailed error messages when debugging rather than the generic 500 error (white screen of death) per this Stack Overflow post:

ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');  //On or Off

I commented out those lines after proving out the code to avoid revealing detailed error messages when running the code in a production scenario. The detailed error messages are useful for potential hackers and may reveal sensitive information about your site.

One more thing... PHP expects semicolons at the end of each statement. You'll save yourself a lot of time debugging if you remember this! 😉

With the background and prerequisites discussed, let's venture on and explore three ways to build dynamic Web APIs using PHP.

Method #1: Use PHP String Replace

We can accomplish the goal using the following code:

<?php

$data = <<<JSON
{
  "Tank": "Tank1",
  "watertemp": {
    "time": "%timestamp",
    "value": %value1
  }
}
JSON;

$timestamp = "2019-05-11 22:20 GMT";
$temperature = 72.5;

$data = str_replace('%timestamp', $timestamp, $data);
$data = str_replace('%value1', $temperature, $data);

header('Content-Type: application/json');
echo $data;

We use the PHP heredoc syntax to define a multiline string containing the JSON template to return. The heredoc syntax starts with a line containing <<< followed by an identifier ("JSON" in the sample above) and ends with a line containing the identifier by itself on a line. The lines in between are stored in a variable called $data.

This JSON template contains special placeholders beginning with "%" (%timestamp and %value1) that we will substitute with our dynamic values of choice. The use of words prefixed with "%" is an arbitrary convention we established, and you could choose something different.

We then use the PHP str_replace function to swap out our placeholder text with our data of choice.

Next, we use the PHP header function to send an HTTP header with the JSON MIME type to ensure the calling program (or web browser) understands the format of the data being returned. This header could be omitted in many contexts, but it adds another level of completeness and correctness and removes ambiguity.

Finally, using the echo command, we output the contents of our $data variable to the HTTP response stream.

Note: My astute readers who have dabbled in PHP programming may observe that I excluded the closing tag "?>" of the PHP block. As noted in the PHP documentation, the closing tag of a PHP block at the end of a file is optional and it may be desirable to not include it in some contexts. I have thus chosen to omit it.

Using the basic framework provided above, we can expand our code to retrieve the current time and generate a random float value that ranges from 72.0 to 73.0 for $temperature.

<?php

function rand_float($min, $max, $decimals)
{
    if ($min > $max) {
        $temp = $min;
        $min = $max;
        $max = $temp;
    }
    $r = (float)rand() / (float)getrandmax();
    $float = ($min + $r * abs($max - $min));
    return number_format($float, $decimals);
}

$data = <<<JSON
{
  "Tank": "Tank1",
  "watertemp": {
    "time": "%timestamp",
    "value": %value1
  }
}
JSON;

// $timestamp = "2019-05-11 22:20 GMT";
$timeFormat = 'Y-m-d H:i T';
$timestamp = gmdate($timeFormat, time());

$low = 72.0;
$high = 73.0;
$decimals = 2;
$temperature = rand_float($low, $high, $decimals);


$data = str_replace('%timestamp', $timestamp, $data);
$data = str_replace('%value1', $temperature, $data);

header('Content-Type: application/json');
echo $data;

Method #2: Use PHP Associative Array with JSON Encoding

Instead of substituting dynamic text for placeholders in a string template, we can utilize a native PHP data structure called an associative array to store key value pairs and ultimately render this data structure as JSON.

Here we go!

<?php

$timestamp = "2019-05-11 22:20 GMT";
$temperature = 72.5;

$data["Tank"] = "Tank1";
$data["watertemp"]["time"] =  $timestamp;
$data["watertemp"]["value"] = $temperature;

$json = json_encode($data, JSON_PRETTY_PRINT);

header('Content-Type: application/json');
echo $json;

We define an associative array called $data for the tank water temperature and utilize the PHP json_encode function to return a JSON representation of the $data array. We also include the optional JSON_PRETTY_PRINT parameter in the json_encode function to return the JSON result with horizontal and vertical whitespace formatting to ensure the JSON is human readable and not just machine (or marginally human) readable.

Our result looks like this:

{
    "Tank": "Tank1",
    "watertemp": {
        "time": "2019-05-11 22:20 GMT",
        "value": 72.5
    }
}

You will notice that the PHP JSON pretty printing uses four spaces for indenting. Our previous string template in method #1 used two spaces which is my preference since I use Prettier with VS Code from my JSON formatting. Either two or four spaces looks fine; however, I did want to highlight this slight output formatting subtlety.

We could, of course, expand this example to make the timestamp and water temperature change dynamically, but at this point I mainly want you to see and understand the mechanics and the high-level differences between method #1 and method #2.

Method #3: Use the ioTSimulator

I expanded method #1 and created a PHP function on GitHub called iotSimulator-php to enable people to create JSON Web APIs to simulate IoT sensor readings. It can also be used in other contexts beyond IoT.

The iotSimulator.php file contains a function for creating JSON Web APIs to simulate IoT sensor readings. You provide a template containing the desired JSON data structure along with the upper and lower random number constraint limits for each sensor reading. As the PHP page is refreshed, new random readings will appear each minute. Readings from previous minutes will retain their values during page refreshes rather than getting replaced with new random data.

To get started, copy iotSimulator.php to a web directory that supports rendering PHP scripts on your hosting provider or local system.

Create a file (for example, tanks.php) in the same web directory and include the following content:

<?php

require('iotSimulator.php');

$template = <<<JSON
  {
    "Tank": "Tank1",
    "watertemp": {
      "time": "%timestamp",
      "value": %val(70,71)
    }
  }
JSON;

$useGMT = true;

// Sample format: 2019-05-10 19:03 GMT
$timeFormat = 'Y-m-d H:i T';
render_json($template, $useGMT, $timeFormat);

Modify the content in the lines following the "$template =" line and the "JSON;" line with the JSON object or objects you desire to render.

The dynamic template fields of interest are:

  • %timestamp - This is substituted with the current timestamp when rendering the page.
  • %val(x,y,[decimals]) - This will render a random number between x and y. If decimals is not supplied, the resulting number will be rounded to 2 decimals.

In our example, we render a random sensor reading between 70 and 71 (with a default of 2 decimal places) for Tank1.

Save the tanks.php file and navigate to the URL in your browser. For example: https://thisdavej.com/api/tanks.php.

The rendered results will look something like this since by default 3 rows (minutes) of data are displayed:

[
  {
    "Tank": "Tank1",
    "watertemp": {
      "time": "2019-05-10 19:03 GMT",
      "value": 70.62
    }
  },
  {
    "Tank": "Tank1",
    "watertemp": {
      "time": "2019-05-10 19:02 GMT",
      "value": 70.55
    }
  },
  {
    "Tank": "Tank1",
    "watertemp": {
      "time": "2019-05-10 19:01 GMT",
      "value": 70.7
    }
  }
]

Note that the PHP function added a "[" at start and a "]" at the end to produce an array of JSON objects with each JSON object rendered based on the template provided.

You can reference the iotSimulator-php GitHub page for the full documentation.

Conclusion

PHP is very handy and can be used for server-side rendering of Web APIs. You could also use it in additional dynamic rendering scenarios such as connecting to databases (MySQL, Postgres, etc.) or real (rather than just simulated) IoT sensor readings. I hope you enjoyed this article and learned something new in the process!

Follow @thisDaveJ (Dave Johnson) on Twitter to stay up to date with the latest tutorials and tech articles.

Additional articles

Fetching, Filtering, and Sorting JSON APIs in Google Sheets: The Missing Functions
Learn Handlebars with Node.js and Help Freddy's Fish Too
How to Count Unique Items in JavaScript Arrays
How to Host a Raspberry Pi Web Server on the Internet with ngrok

Last updated May 13 2019

Share

One thought on “Three Ways to Build Dynamic Web APIs using PHP

Leave a Reply

Your email address will not be published. Required fields are marked *