drew.d.lenhart

programming, software, technology, anything on my mind...

Getting Started with a JSON API using Slim!

2016/01/31

I am going to show you how easy it is to get started with creating your own JSON API using Slim! This is useful for creating a multitude of different platform applications that can read one common data set.

In my professional career I use AMCharts pretty religiously. AMCharts is a great HTML5 dynamic chart library for creating line graphs, bar graphs, pie charts, trending charts, etc. Another great feature with this library is it's ability to read JSON data to feed whatever you want. And this is where SLIM comes in.

For the sake of this demonstration we'll create a MySQL database with a table to hold a computer's CPU/MEMORY/C:Drive utilization. We'll only put in mock data for the demonstration unless you want to write a script to gather the information and insert into this database on regular intervals!

This is a demonstration, don't use this code on your production system unless there is some form of authentication!

Folder Structure

Since we are only creating a JSON API, this project will be pretty slim. Create the following files, an includes folder with database.class.php, index.php in root, composer.json in root, and .htaccess in root:

Screen Shot 2016-01-27 at 6.29.52 AM

Database

If you are pretty familiar with PHPMyAdmin, go ahead and create a database and create a table named: c_utilization.

Screen Shot 2016-01-26 at 9.05.57 PM

Also as usual, grant a user read/write privileges and take note for the database connection.

In includes/database.class.php, use this connection code and helper methods:


<?php
/*
    Author:  Drew D. Lenhart
    http://www.drewlenhart.com
    Page: database.class.php
    Desc: Get connected to DB.  
    */
class database
{
    public $pdo;
    private static $instance;

    private function __construct(){
        $db_username = "username";  //database username
        $db_password = "password";  //database password
        $db_name = "databasename";  //database name
        $host = "localhost";  //usually localhost

    try{
        $this->pdo = new PDO('mysql:host='. $host .';dbname='.$db_name, $db_username, $db_password);
    }
        catch ( PDOException $exception ){
                echo "Connection error :" . $exception ->getMessage();
    }
    }

    public static function getInstance(){
        if (!isset(self::$instance))
        {
            $object = __CLASS__;
            self::$instance = new $object;
        }
        return self::$instance;
    }

    //Grab single entry
    function getDataSingle($query){
        $queryEx = $this->pdo->prepare($query);
        $queryEx->execute();
        return $queryEx->fetch(PDO::FETCH_ASSOC);
    }

    //Grab multiple entries
    function getData($query){
        $queryEx = $this->pdo->prepare($query);
        $queryEx->execute();
        return $queryEx->fetchAll(PDO::FETCH_ASSOC);
    }

}

?>
This is a slimmed down version of my database connection class and have used in other projects. I began writing a tutorial on how to use Eloquent ORM for database work, but for this demonstration we wont use it here.

**Insert some mock data to have something to test with.


Composer

Composer is a PHP package dependency manager. I talked a little about it here. There is a Windows installer which is a pretty easy method of getting started. The other method for Linux/OSX is really simple. Go into the project directory, type the following command in the terminal (I'm on a MAC):

curl -sS https://getcomposer.org/installer | php

This command creates a composer.phar file that can be used to run Composer commands.

We only need one package, and that is Slim! In composer.json add the following:


{
    "require": {
        "slim/slim": "~2.6"
    }
}

Now run the following Composer command to download and install Slim! This command generates a vendor folder with the included packages, in this case, just Slim:

composer.phar install

Nuts and Bolts

For Slim to do the proper url routing, we need a couple things, open the .htaccess file and input:


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

This is a rewrite rule and tells requests to route through the index.php file. Mod_rewrite also needs to be enabled ( if using Apache ). More info.

Now we are ready to begin the index.php file. Before hand we need to map out a couple url routes. For this demonstration we only need a couple.

http://localhost/ <- Main page, just echo plain text http://localhost/api/getUtilization <- Get all entries ordered by date http://localhost/api/getCurrentUtil <- Get latest entry

Full index.php code:


<?php
/*
Title:              stJSONAPI - Tutorial Code
DESC:               Json api example
Auth:               Drew Lenhart - www.drewlenhart.com
Last Update:        01/05/15

Database info:
c_id = ID; c_cpu = CPU; c_mem = MEMORY; c_cdrive = c: DRIVE; c_date = TIMESTAMP
*/

require 'vendor/autoload.php';
require 'includes/database.class.php';

$app = new SlimSlim();

/*#### - MAIN - ####*/
$app->get('/', function() use($app) {
    $app->response->setStatus(200);
    echo "Welcome to my JSON API!";
}); 

/*
#### - GET CURRENT UTILIZATION/ALL NUMBERS - ####
e.g.
http://localhost/api/getUtilization = get all entries.
http://localhost/api/getCurrentUtil = get current entry.
*/
$app->get('/api/:type', function($type) use($app) {

    $db = database::getInstance();

    try 
    {
        $sql = "SELECT * FROM c_utilization ORDER BY c_date DESC";

        //use get $type from URL and use helper methods in database.class.php
        If ($type == 'getUtilization'){

            $stmt = $db->getData($sql);

        }else if ($type == 'getCurrentUtil'){

            $stmt = $db->getDataSingle($sql);

        }else{
            echo "Incorrect parameter!  Please check url.";
            break;
        }

        if($stmt) {
            $app->response->setStatus(200);
            $app->response()->headers->set('Content-Type', 'application/json');
            $app->response()->headers->set('Access-Control-Allow-Origin', '*');
            echo json_encode($stmt);
            $db = null;
        } else {
            throw new PDOException('No records found.');
        }

    } catch(PDOException $e) {
        $app->response()->setStatus(404);
        $app->response()->headers->set('Access-Control-Allow-Origin', '*');
        echo '{"error":{"text":'. $e->getMessage() .'}}';
    }

});

//RUN!!
$app->run();

A couple things to note in the above code:

  • require 'vendor/autoload.php'; <- Composer generates the autoload file with our dependancies. (Slim in this case).
  • $app = new SlimSlim(); <- Initiate new Slim object.
  • $app->get('/', function() use($app) {echo "Welcome"}); <- Format for creating route.
  • $app->response->setStatus(200); <- Sets status code, can be used to set various codes depending on desired output. E.g. 401 for Unauthorized.
  • $app->response()->headers->set('Content-Type', 'application/json'); <- Sets the document type to JSON.
  • $app->response()->headers->set('Access-Control-Allow-Origin', '*'); <- Allows for cross domain readability.
  • echo json_encode($stmt); <- Echo out entries in JSON format.
  • $app->run(); <- Run the application.

Testing

Theres a couple ways to test. Open up a web browser and see if JSON data displays using the three possible routes:

http://localhost/ http://localhost/api/getUtilization http://localhost/api/getCurrentUtil

Or use curl to test for proper status codes:

curl -i http://localhost/api/getUtilization
Screen Shot 2016-01-27 at 7.21.14 AM

In a browser window:

Screen Shot 2016-02-03 at 7.58.53 PM

Final Notes

This is obviously a very simple start. So much more can be done to this. For example creating POST routes to enter data:

$app->;post('/insertEntry', function() {

//Grab post variables, validate, etc

//Insert into database

});

Authentication really needs to be considered. Unless you want a very open API (Not recommended especially if you are inserting data to database!), you should be using tokens. Read more on a Slim Middleware package for token authentication.


Thats it! Now that there is a JSON API, this data can be used for AMCharts! I'll cover creating charts in another tutorial. Thanks for reading!

--Drew