JSON : API

 

When attempting to connect to a JSON API to pull down data and display on a PHP generated page, suprisingly I had a lot of trouble finding resources that explain the process.  Many of the articles explained how to connect to a JSON resource, but didn’t go into detail how to implement authentication tokens.

To help others who may be trying to create dynamic content from a JSON API URL, I have documented some of the things I’ve learned below.

The Project

My project brief was to dynamically display bible readings, pulling the readings from the ESV API (esv.org).  The API Is pretty simple, as in you send the bible book, chapter and verse (optional) to a URL, and it would return the result in a JSON result.  Results are available in text or pre-formatted HTML (with classes to allow CSS formatting).

The API documentation page has a neat form that allows you to choose the parameters, that generates a URL you can test in the browser.  Pasting a URL into a browser address bar works perfectly, but when calling the URL from a PHP it returned a “not authorised” result.

Setting up Authentication (CURL) to the API

The ESV API required the use of an authorisation token, unique to the project.  Applying for the token was as easy as filling in the online form.  Now I had the Authorisation token, the question was “Where do I put this in the code to authenticate before I make the API request?!”.  After some time Googling I discovered that authentication is set in the HTTP Header.

I’m not 100% sure how this works, but I imagine it stores the CURL initialisation variables in memory, then sends the authentication to the API along with the request for the content – I found this is sent to the API in a CURL_EXEC request.  I found some code (website source unknown) that provided a snippet of code that used CURL to set the connection options, then I fed the URL into the CURL execution, which returned data into a new variable.

// Initialise CURL
$ch = curl_init($URL_String);

// Returns the data/output as a string instead of raw data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Good practice to let people know who's accessing their servers. See https://en.wikipedia.org/wiki/User_agent
curl_setopt($ch, CURLOPT_USERAGENT, 'YourScript/0.1 (my@emailaddress.com)');

//Set your auth headers
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
   // 'Authorization: Bearer ' . $TOKEN
	'Authorization: Token 1234567890abcdef'   //This is the Authentication Token that I applied for at esv.org
    ));

// get stringified data/output. See CURLOPT_RETURNTRANSFER
$data = curl_exec($ch);

Dealing with the data returned from the API

Once the result was stored in the $data field, it was just a matter of using ECHO to display the content on screen.

Dynamic requests

This project required that a string could be fed to the URL to dynamically return bible readings to the end user.  For this I used $_GET to grab a variable from the URL and feed it into the URL that was sent to the ESV API.

I also found the API didn’t like spaces in the URL, so I had to replace spaces with the %20 ASCII code

Here’s the code for that:

//This gets the text in the 'reading' URL parsed variable, then replaces any spaces with %20
$Passage_NoSpace = str_replace(" ","%20",$_GET["reading"]);
//Set up the full URL to send to the API
$URL_String='https://api.esv.org/v3/passage/html/?q=' . $Passage_NoSpace . "&include-footnotes=false";

Changing the link text to an icon using CSS

Using the CSS after tag I was able to place a speaker icon (from FontAwesome) next to the “Listen” text.  To remove the text I just set the text font size to 0.

  .mp3link{text-transform: lowercase; font-size:0;}
  .mp3link:after{font-size:28px;font-family: FontAwesome;content: "\f028";}

The final product!

With some CSS styling and some sliding animation we have made the UI on a mobile feel like you are sliding your finger to turn the page.

The bible reading app can be seen live in the Life Christian Church AU app, or through a browser at http://lifechristianchurch.org.au/readingplan_ESV.php?reading=Numbers%2010-11, but I’ve also provided the full code (minus authenitcation keys) for anyone else who would like to implement this solution on their church website.

<head>
  <meta name="description" content="Life Christian Church Bible Reading Plan - Readings">
  <meta name="author" content="Gary Walker - February 2018">
  
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<link href="https://fonts.googleapis.com/css?family=Muli" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>

</head>

<style>
  h1, h2, h3, h4, h5, h6 {text-align: center;font-family: 'Muli',Helvetica,Arial,Lucida,sans-serif; text-transform: uppercase;}
  p{font-size: 18px;margin:20px 0 20px 0;}
  body{background:#E9ECEF; margin:0 10px 0 10px;}
  .mp3link{text-transform: lowercase; font-size:0;}
  .mp3link:after{font-size:28px;font-family: FontAwesome;content: "\f028";}
  
</style>


<html>
<body>

<div class="animated slideInRight container-fluid">
<p align="center">
	<a href="javascript:history.back()" class="btn btn-secondary btn-lg active" role="button" aria-pressed="true">Back</a>
</p>
<?php
//setup the request, you can also use CURLOPT_URL

//This gets the text in the 'reading' URL parsed variable, then replaces any spaces with %20
$Passage_NoSpace = str_replace(" ","%20",$_GET["reading"]);
//Set up the full URL to send to the API
$URL_String='https://api.esv.org/v3/passage/html/?q=' . $Passage_NoSpace . "&include-footnotes=false";

//echo $URL_String.'<br><br>';
$ch = curl_init($URL_String);

// Returns the data/output as a string instead of raw data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Good practice to let people know who's accessing their servers. See https://en.wikipedia.org/wiki/User_agent
curl_setopt($ch, CURLOPT_USERAGENT, 'YourScript/0.1 (my@emailaddress.com)');

//Set your auth headers
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
   // 'Authorization: Bearer ' . $TOKEN
	'Authorization: Token 1234567890abcdef'
    ));

// get stringified data/output. See CURLOPT_RETURNTRANSFER
$data = curl_exec($ch);

$Reading = json_decode($data, true);
//echo 'Verse Searched: ' . ($_GET["reading"]) . '!';
echo $Reading['passages'][0];

// get info about the request
$info = curl_getinfo($ch);

// close curl resource to free up system resources 
curl_close($ch)
?>

<p align="center">
	<a href="javascript:history.back()" class="btn btn-secondary btn-lg active" role="button" aria-pressed="true">Back</a>
</p>
</div>

</body>
</html>