17 May
2016

Shane Todhunter

By

We develop API’s very regularly at 14 Oranges, being that almost every app we have developed requires some sort of back end data source. Developing an API is really not a difficult process but there are lots of little things to consider and building one from scratch is just not always the best use of your time. We do about 90% of our server side development in php and have over the past 15 years done everything from creating our own frameworks to using popular frameworks like Cake, laravel, symfony, zend and codeigniter. But up until this week I had always ignored Slim framework. I figured if I didn’t need all the bells and whistles on a project offered by a full featured framework, I would be better just going to my own toolset.

Andrew, one of our developers, mentioned recently he was using Slim for an api related project, so when I had to develop a really quick proof of concept for a client recently, I figured I would take the time to try it out and I thought I would put some notes down for other developers that might be curious. I ended up turning it into a presentation for our company and decided to share my findings here in this post.

I figured I would jump right in and install it, then look at a few examples, write some code and get it working before reading the documentation. I know, I know, RTFM, and I do … eventually. But I am a quick study and manuals more often than not put me to sleep.

My shortcut in this case paid off. I hadn’t gotten to reading the manual yet and my API was working as intended.. So I guess what I am saying is learning curve on Slim is really low.

I began by installing it via composer. You will have to have php installed first to complete this.

On my mac I created a new directory, opened up terminal and navigated to that directory and simply installed composer with this command.

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

There are a couple routes to take next. You could install just the Slim framework and go from there or you could start with the slim-skeleton which basically does some of the initial setup for you and points you in the right direction. I went with the basic install but in retrospect I think installing the skeleton would be a better option.

I created my composer.json file containing the following:

{
   "require": {
     "slim/slim": "^3.0"
   }
 }

Lastly installed via composer with:

php composer.phar install

There you have it … took about 1 minute.

I created my index.php file and added some rewrite rules to ensure all requests were routed to this file in an .htaccess file. Lots of tutorials out there on how to do this so I will skip it. Inside the index.php file I had to require the autoload.php file that the Slim installation created, instantiate Slim and get going on my routing. Here is what that looks like.

<?php
 use \Psr\Http\Message\ServerRequestInterface as Request;
 use \Psr\Http\Message\ResponseInterface as Response;
require 'vendor/autoload.php';

The Slim Framework’s router is built on top of the nikic/fastroute component, and its fast and easy to use. Here is what my index.php file ended up looking like with my first route defined, a base route basically just saying you need to authenticate.

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
$app = new \Slim\App;
 
$app->any('/', function (Request $request, Response $response) {
   $response->getBody()
   ->write("Welcome to the API. Please authenticate.")
   ->withHeader(''Content-type', 'application/json');
   return $response;
 });

 $app->run();
?>

The use statements at the top of the script are bringing the Request and Response classes in. Slim framework now supports PSR-7, a PHP standard for HTTP messaging. We then setup $app to contain an instance of Slim and add a route. When adding a route to a Slim application you can choose an HTTP request method (POST, GET, PUT, OPTIONS, PATCH, DELETE) or as I have done in this case you can allow the listener to accept requests with any HTTP method.

Every HTTP request has a method that is typically one of:

OPTIONS – a request for information about the communication options available on the request/response chain identified by the Request-URI.

GET – retrieve whatever information (in the form of an entity) is identified by the Request-URI.

HEAD – identical to GET except that the server MUST NOT return a message-body in the response.

POST – used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI

PUT – requests that the enclosed entity be stored under the supplied Request-URI.

DELETE – requests that the origin server delete the resource identified by the Request-URI

PATCH – requests that the items in the enclosed entity be stored under the supplied Request-URI (not a wholesale update).

SLIM implements each of these methods and allows you to create your own custom methods as well. The methods are not strictly enforced by SLIM so you can work with them as you see fit. You could really throw the other devs for a loop by returning error code 69 on HEAD but I really would not recommend that.

The second parameter for the route method is the callback function which is being passed the PSR-7 request and response objects. A route can look at the request and manipulate the response as required then return the response. Once all of the logic and business stuff is done you run the $app and away we go.

So in about 5 minutes of coding we have our api’s first endpoint operational. Any request to the base url of our API will respond with a 200 HTTP status (default in Slim) with a JSON content type and a response body of ‘Welcome to the API. Please authenticate.’.

Obviously the API the way it stands now is not overly useful but all we have to do is add our routes corresponding to the endpoints of our API and we will have the job done. So here is a full API implementing a really simple Authentication endpoint. Obviously this is not something I would use in the real world but it is a great example of how fast and easy Slim is to use.

<?php
 // INCLUDING THE PSR 7 REQUEST AND RESPONSE CLASSES
 use \Psr\Http\Message\ServerRequestInterface as Request;
 use \Psr\Http\Message\ResponseInterface as Response;
 
// AUTOLOAD UP SLIM
 require '../vendor/autoload.php';
 
$app = new \Slim\App;

 // DEFINE AN AUTH ENDPOINT ACCESSIBLE VIA POST REQUESTS
 $app->post('/auth/',function (Request $request, Response $response) {
   $allPostVars = $request->getParsedBody();
   if($allPostVars['username'] !== "shane@14oranges.com" || $allPostVars['password'] !==password_hash("superSecretPassword")) {
     $app->halt(403, 'Invalid Credentials.');
   }else {
     $token = password_hash ('SuperSecretToken');
     echo json_encode(array("status" => "success", "code" => 1, "token" => $token, "message"=> "App API Success" ));
   }
 });
// DEFINE A TICKETS ENDPOINT AVAILABLE VIA GET
 $app->get('/tickets', function (Request $request, Response $response) {
   if($token !== password_hash ('14Oranges')) {
     $app->halt(403, 'Invalid Token.');
   } else {
      $mapper = new TicketMapper($this->db);
      $tickets = $mapper->getTickets();
     $response->getBody()->write(var_export($tickets, true));
     return $response;
   }
 });
 $app->run();
 ?>

So there you have it. An Auth endpoint listening for username/passwordhash returning a token on success. A tickets endpoint sending back a list of tickets and verifying a valid token. All said and done very quickly. There are lots of useful features that I haven’t illustrated here but the documentation is good and the community is also pretty active so you can pretty easily find the answer you need.

Lots of handy helpers

Slim comes with a bunch of helper methods as well. Pretty self explanatory and easy to use. Here are a few examples.

$headers = $request->getHeaders();

$headerValueArray = $request->getHeader(‘Accept’);

$contentType = $request->getContentType();

$mediaType = $request->getMediaType();

$charset = $request->getContentCharset();

$length = $request->getContentLength();

$parsedBody = $request->getParsedBody();

$body = $request->getBody();

 

My Findings

Slim is small, fast and easy to use. I would definitely recommend trying it out if you are developing an api. Keep in mind that Slim takes a barebones approach to development, though. The routing is basic yet functional, but relies on the developer being able to extend it. The Slim team realize this, and have made it easy to do so, notably with middleware and their use of Dependency Injection.

Templating is available too. Slim ships with support for Twig and PHP-View, but there are many other options as well. There are some very useful organizational tools such as route hierarchy and groupings allowing you to keep a complex API well organized.

I am not about to get Slim Framework tattooed across my back at this point but I know a few guys that might!.image00