In the past few months, I had to integrate some of our projects with several 3rd party vendors. Whether, it’s a Magento eCommerce site or a WordPress site, the needs are the same: allowing several software components (or web in this case) to interact with each other.

Lately, APIs have taken on a whole new life. The programmableweb.com APIs directory is referencing more than 11,000 public APIs, which is just the tip of the iceberg. There are also many private and internal ones.

I won’t cover how to call APIs as we mostly all do it without sometimes noticing it (Facebook login, Twitter feed, etc.).

If you’re developing in PHP, you might have already used cURL to call APIs but to make your life easier I would recommend checking out Guzzle. As advertised, it does “take the pain out of consuming web services”.

Build Your Own REST API in PHP with SLIM

1) Why would I build one?

  • You want a scalable and easy way to expose resources or features of your site/app.
  • You are working on an existing project that you didn’t start and you may not want to extend the legacy code directly.
  • Your project is not based on a framework (I feel sorry for you) or is using a framework that doesn’t offer RESTful mechanisms.

If you find yourself in one of these positions (there are more) you may want to build your own REST API. I’ll assume from here that you have worked with APIs and Web Services and understand the REST architecture style.

I highly recommend the SLIM framework if you’re working in a PHP environment.

2) SLIM framework

SLIM is a PHP open-source micro-framework. It has a powerful URL router, it is lightweight and supports authentication and multiple request/response formats. I used it successfully in several projects, from WordPress, Magento, Yii to legacy code.

a) Installation using Composer

– After setting up a classic AMP (Apache MySQL PHP) environment, create a new project/directory in your web root and create a composer.json file in your project root:

{
    "require": {
        "slim/slim": "2.*"
    }
}

(Follow these steps to install Composer in your project)

– Install via composer:

$ php composer.phar install

– Create a index.php file for your app and paste this content to autoload SLIM:

require 'vendor/autoload.php';
b) Hello World

Add this to your index.php file

$app = new SlimSlim();

//Define an HTTP GET route "hello" with a $name parameter
$app->get('/hello/:name', function ($name) {
    echo "Hello, $name";
});

$app->run();

And now go to your app URL, that would look like http://localhost/myapi/hello/Bob
Your page should now display: “Hello Bob”.

Yup, in 4 lines, you built your first REST API!

3) Possibilities

Now that you have a working API setup in your project you might want to use it for one of your existing projects.

a) Resource access example

You have a list of resources, let’s say a list of customers from a MySQL database (name, email, address, etc) and you want to be able to access it from a native mobile app or a 3rd party CMS.

Let’s create a GET route that returns all the customers in JSON format:

// handle GET requests for /customers
$app->get('/customers', function () use ($app) {
  // query database for all customers
  $customers = **Some PDO code to retreive all records from your customer table**

  // send response header for JSON content type
  $app->response()->header('Content-Type', 'application/json');

  // return JSON-encoded response body with query results
  $app->response()->setBody(json_encode($customers));
});

Now that we can get the list of customers, we may want to be able to add one. So we’ll create a POST route for /customers that inserts a JSON customer in the table.

// handle POST requests to /customers
$app->post('/customers', function () use ($app) {    

    // get and decode JSON request body
    $request = $app->request();
    $body = $request->getBody();
    $input = json_decode($body); 

    // create customer
    $customerArray = array(
	'name' => (string)$input->name,
	'email' => (string)$input->email,
	'address' => (string)$input->address,

	// store customer
	$customer = **Some PDO code to insert $customerArray in your customer table and return the created record**
);
    // return JSON-encoded response body
    $app->response()->setBody(json_encode($customer));
});

To test your API, I recommend the Postman Chrome extension. It’s the best REST client I used so far.

Once installed and opened, send a POST request to the URL http://localhost/myapi/customers

With a JSON request like:

{
        "name": "Clique Studios",
        "email": "test@cliquestudios.com",
        "address": "410 S Michigan Ave, 908"
}

Once submitted, your new customer will be inserted in your table.

To improve this example, try adding a GET route to return a specific customer using a parameter “id” like in the “Hello World” example. Then add a PUT route to update a customer and a DELETE route to remove one.

This code will also need to handle exceptions, take a look at SLIM’s doc. For example, you should return a HTTP status code “404” if a customer can’t be found.

b) Magento and WordPress

Let’s say you need to expose your Magento products to a 3rd party in a way the native REST API can’t do. If you don’t feel like extending the Magento REST API or WordPress API and you just need a couple of endpoints, then you might consider using SLIM. You will however have to build your own authentication as your SLIM API will not use either Magento’s or WordPress’.

After calling

// Magento
require_once MAGENTO_PATH.'app/Mage.php';
Mage::app();
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

Or

//Wordpress
require_once WP_PATH.'wp-blog-header.php';

You can start using WordPress or Magento in your API routes. You could make a POST route to create custom post types in WordPress or make a GET route to return Magento’s orders with specific logic and custom attributes.

c) Extra – Logging

Create a “log” directory in the root of your project (same level as index.php) and replace

$app = new SlimSlim();

with

$fpLog = fopen('log/log-'.date('Ymd'), 'c');
fseek($fpLog, -1, SEEK_END);
$logWriter = new SlimLogWriter($fpLog);

$app = new SlimSlim(array(
	'log.writer' => $logWriter,
));

// Logs all the requests/responses in a specific file per day
$app->hook('slim.after', function () use ($app) {
	$request = $app->request;
	$response = $app->response;

	$app->log->debug('*** Time: ' . date('Y-m-d h:i:s'));
	$app->log->debug('*** Request URL: ' . (string)$request->getUrl());
	$app->log->debug('*** Request Path: ' . (string)$request->getPath());
	$app->log->debug('*** Request Method: ' . (string)$request->getMethod());
	$app->log->debug('*** Request Body: ' . (string)$request->getBody());
	$app->log->debug('*** Response: '. (string)$response->getBody());
	$app->log->debug('====================');
	$app->log->debug('');
});

Each time your API is called, this will log the complete request and response in a text file. Your debugging will be much easier.

Conclusion

This post is just an introduction to APIs and how to build your own. With the right tool, it is relatively easy to expose your resources or features. Please note, the examples above do not cover testing, exception handling, or authentication. These should be addressed as soon as you start because your resources will be available to anybody as soon as you create your routes. You want to make sure that you’re tracking who can access what and how many times (cf: API limits for Google).

APIs are great time savers. They allow developers to mix services like Facebook login, Google Maps or Twitter and come up with entirely new apps. But you should also remember that building your own API also implies that other developers/services might rely on it and shutting it down will also shut down their services. The example of Twitter changing its app version recently showed how dangerous relying on an API can be.