77

The issue is this: I have a web application that runs on a PHP server. I'd like to build a REST api for it.
I did some research and I figured out that REST api uses HTTP methods (GET, POST...) for certain URI's with an authentication key (not necessarily) and the information is presented back as a HTTP response with the info as XML or JSON (I'd rather JSON).

My question is:

  1. How do I, as the developer of the app, build those URI's? Do I need to write a PHP code at that URI?
  2. How do I build the JSON objects to return as a response?
Henke
  • 4,445
  • 3
  • 31
  • 44
Sharon Haim Pour
  • 6,595
  • 12
  • 42
  • 64
  • 1
    http://www.gen-x-design.com/archives/create-a-rest-api-with-php/ is a great resource on this. – Geoffrey Wagner Jan 13 '11 at 19:34
  • I wrote this [blog post](https://www.leaseweb.com/labs/2015/10/creating-a-simple-rest-api-in-php/) containing some example code and instructions for this. – mevdschee Jan 27 '16 at 21:55

7 Answers7

69

Here is a very simply example in simple php.

There are 2 files client.php & api.php. I put both files on the same url : http://localhost:8888/, so you will have to change the link to your own url. (the file can be on two different servers).

This is just an example, it's very quick and dirty, plus it has been a long time since I've done php. But this is the idea of an api.

client.php

<?php

/*** this is the client ***/


if (isset($_GET["action"]) && isset($_GET["id"]) && $_GET["action"] == "get_user") // if the get parameter action is get_user and if the id is set, call the api to get the user information
{
  $user_info = file_get_contents('http://localhost:8888/api.php?action=get_user&id=' . $_GET["id"]);
  $user_info = json_decode($user_info, true);

  // THAT IS VERY QUICK AND DIRTY !!!!!
  ?>
    <table>
      <tr>
        <td>Name: </td><td> <?php echo $user_info["last_name"] ?></td>
      </tr>
      <tr>
        <td>First Name: </td><td> <?php echo $user_info["first_name"] ?></td>
      </tr>
      <tr>
        <td>Age: </td><td> <?php echo $user_info["age"] ?></td>
      </tr>
    </table>
    <a href="http://localhost:8888/client.php?action=get_userlist" alt="user list">Return to the user list</a>
  <?php
}
else // else take the user list
{
  $user_list = file_get_contents('http://localhost:8888/api.php?action=get_user_list');
  $user_list = json_decode($user_list, true);
  // THAT IS VERY QUICK AND DIRTY !!!!!
  ?>
    <ul>
    <?php foreach ($user_list as $user): ?>
      <li>
        <a href=<?php echo "http://localhost:8888/client.php?action=get_user&id=" . $user["id"]  ?> alt=<?php echo "user_" . $user_["id"] ?>><?php echo $user["name"] ?></a>
    </li>
    <?php endforeach; ?>
    </ul>
  <?php
}

?>

api.php

<?php

// This is the API to possibility show the user list, and show a specific user by action.

function get_user_by_id($id)
{
  $user_info = array();

  // make a call in db.
  switch ($id){
    case 1:
      $user_info = array("first_name" => "Marc", "last_name" => "Simon", "age" => 21); // let's say first_name, last_name, age
      break;
    case 2:
      $user_info = array("first_name" => "Frederic", "last_name" => "Zannetie", "age" => 24);
      break;
    case 3:
      $user_info = array("first_name" => "Laure", "last_name" => "Carbonnel", "age" => 45);
      break;
  }

  return $user_info;
}

function get_user_list()
{
  $user_list = array(array("id" => 1, "name" => "Simon"), array("id" => 2, "name" => "Zannetie"), array("id" => 3, "name" => "Carbonnel")); // call in db, here I make a list of 3 users.

  return $user_list;
}

$possible_url = array("get_user_list", "get_user");

$value = "An error has occurred";

if (isset($_GET["action"]) && in_array($_GET["action"], $possible_url))
{
  switch ($_GET["action"])
    {
      case "get_user_list":
        $value = get_user_list();
        break;
      case "get_user":
        if (isset($_GET["id"]))
          $value = get_user_by_id($_GET["id"]);
        else
          $value = "Missing argument";
        break;
    }
}

exit(json_encode($value));

?>

I didn't make any call to the database for this example, but normally that is what you should do. You should also replace the "file_get_contents" function by "curl".

Ari
  • 4,643
  • 5
  • 36
  • 52
Simon marc
  • 1,003
  • 7
  • 8
  • Simon, thank you very much for your example. I just want to be sure: Suppose I have resource called User, then I need to put the API file in: http://www.mydomain.com/api/user Correct? – Sharon Haim Pour Jan 18 '11 at 18:15
  • You can name the file like you want. But yes, it's way better to call the file with a explicite name. Look in my api file I check the get parameter and call a function thanks to this value. You can do a include of user.php and call a function which is in this file, Or you can put the file at api/user and handle the parameters from here. – Simon marc Jan 18 '11 at 19:36
  • So basically, I need to update the server routing table to map certain URL's to certain PHP file on the server. Correct? – Sharon Haim Pour Jan 19 '11 at 00:54
  • 1
    Yes, but that the same as creating a normal website, is just the kind of information you're sending back whom change. – Simon marc Jan 20 '11 at 14:55
  • Can I use REST for sending SMS in telco? – XxXk5XxX Sep 10 '14 at 09:53
  • You might want to set content type header as `application/json` (http://stackoverflow.com/questions/4064444/returning-json-from-a-php-script) and, in case of angular (etc), a `callback argument` might come in handy (http://stackoverflow.com/questions/12066002/parsing-jsonp-http-jsonp-response-in-angular-js). – jsruok Oct 23 '14 at 11:36
  • 6
    This only uses "GET" and never looks at the request method, so it is not *RESTful*. See http://stackoverflow.com/a/897311/1766230 for an example, and http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services – Luke Apr 04 '15 at 16:27
34

In 2013, you should use something like Silex or Slim

Silex example:

require_once __DIR__.'/../vendor/autoload.php'; 

$app = new Silex\Application(); 

$app->get('/hello/{name}', function($name) use($app) { 
    return 'Hello '.$app->escape($name); 
}); 

$app->run(); 

Slim example:

$app = new \Slim\Slim();
$app->get('/hello/:name', function ($name) {
    echo "Hello, $name";
});
$app->run();
holographic-principle
  • 19,688
  • 10
  • 46
  • 62
  • 1
    Thank you. I used Slim and I had a bare api running in a few minutes. – user12345 Oct 09 '13 at 19:10
  • What would you recommend for a more complicated (detailed) apis ?Slim is handy but all the functions is in a single file so the readability is quite hard. – Ilker Baltaci Feb 25 '14 at 14:44
  • 2
    @IlkerBaltaci With Silex, you can extract the controllers into classes. Here's a good write-up on that, and some of the pros and cons of using a micro-framework vs a full-stack framework https://igor.io/2012/11/09/scaling-silex.html . I personally prefer Silex as it gives me the most important things and lets me choose the rest of my stack. – holographic-principle Feb 25 '14 at 15:33
11

That is pretty much the same as created a normal website.

Normal pattern for a php website is:

  1. The user enter a url
  2. The server get the url, parse it and execute a action
  3. In this action, you get/generate every information you need for the page
  4. You create the html/php page with the info from the action
  5. The server generate a fully html page and send it back to the user

With a api, you just add a new step between 3 and 4. After 3, create a array with all information you need. Encode this array in json and exit or return this value.

$info = array("info_1" => 1; "info_2" => "info_2" ... "info_n" => array(1,2,3));
exit(json_encode($info));

That all for the api. For the client side, you can call the api by the url. If the api work only with get call, I think it's possible to do a simply (To check, I normally use curl).

$info = file_get_contents(url);
$info = json_decode($info);

But it's more common to use the curl library to perform get and post call. You can ask me if you need help with curl.

Once the get the info from the api, you can do the 4 & 5 steps.

Look the php doc for json function and file_get_contents.

curl : http://fr.php.net/manual/fr/ref.curl.php


EDIT

No, wait, I don't get it. "php API page" what do you mean by that ?

The api is only the creation/recuperation of your project. You NEVER send directly the html result (if you're making a website) throw a api. You call the api with the url, the api return information, you use this information to create the final result.

ex: you want to write a html page who say hello xxx. But to get the name of the user, you have to get the info from the api.

So let's say your api have a function who have user_id as argument and return the name of this user (let's say getUserNameById(user_id)), and you call this function only on a url like your/api/ulr/getUser/id.

Function getUserNameById(user_id)
{
  $userName = // call in db to get the user
  exit(json_encode($userName)); // maybe return work as well.
}

From the client side you do

    $username = file_get_contents(your/api/url/getUser/15); // You should normally use curl, but it simpler for the example
// So this function to this specifique url will call the api, and trigger the getUserNameById(user_id), whom give you the user name.
    <html>
    <body>
    <p>hello <?php echo $username ?> </p>
    </body>
    </html>

So the client never access directly the databases, that the api's role.

Is that clearer ?

Simon marc
  • 1,003
  • 7
  • 8
  • +1. Also to note, the API should set the right content type for the response. For json, see http://stackoverflow.com/questions/477816/the-right-json-content-type – Ben Jan 13 '11 at 23:38
  • So I should have on the server one php API page that manages all the requests? – Sharon Haim Pour Jan 14 '11 at 00:17
  • No, wait, I don't get it. "php API page" what do you mean by that ? – Simon marc Jan 14 '11 at 03:52
  • My question is where should the API requests should be pointed to? To which file on the server? – Sharon Haim Pour Jan 14 '11 at 20:07
  • Which files you want, It's exactly the same as created a website, except you call the api from a client, and not from a browser. But for the api nothing change. When you receive the url on the serveur, you decide what to do with it, thanks to get and post parameter. Did you already make a website ? Did you use a framework like cake, symfony or zend ? – Simon marc Jan 14 '11 at 21:13
  • If you really need it, I'll write you a very little api call to show you exactly how that's work, in simple php (I don't want to create a whole framework project just for a example). (and not before sunday) – Simon marc Jan 14 '11 at 21:15
  • Thank you for your help. My website is already up and running and I didn't use any framework to build it. The server side is written with PHP. I'd appreciate if you could do so and write some kind of API call. – Sharon Haim Pour Jan 14 '11 at 23:14
  • No problem, but Let me just a couple of day, I very busy with one of my project right now. (Don't hesitate to re-comment if I forget). – Simon marc Jan 15 '11 at 04:23
  • I'm sorry, I've a lot of work right now. I'll try to do it tonight. – Simon marc Jan 17 '11 at 13:33
  • I just but you a little example. I try it and it work fine. Tell me if you get everything. – Simon marc Jan 18 '11 at 00:31
8

(1) How do I ... build those URI's? Do I need to write a PHP code at that URI?

There is no standard for how an API URI scheme should be set up, but it's common to have slash-separated values. For this you can use...

$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

...to get an array of slash-separated values in the URI after the file name.

Example: Assuming you have an API file api.php in your application somewhere and you do a request for api.php/members/3, then $apiArgArray will be an array containing ['members', '3']. You can then use those values to query your database or do other processing.

(2) How do I build the JSON objects to return as a response?

You can take any PHP object and turn it into JSON with json_encode. You'll also want to set the appropriate header.

header('Content-Type: application/json');
$myObject = (object) array( 'property' => 'value' ); // example
echo json_encode($myObject); // outputs JSON text

All this is good for an API that returns JSON, but the next question you should ask is:

(3) How do I make my API RESTful?

For that we'll use $_SERVER['REQUEST_METHOD'] to get the method being used, and then do different things based on that. So the final result is something like...

header('Content-Type: application/json');
$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1));
$returnObject = (object) array();
/* Based on the method, use the arguments to figure out
   whether you're working with an individual or a collection, 
   then do your processing, and ultimately set $returnObject */
switch ($_SERVER['REQUEST_METHOD']) {
  case 'GET':
    // List entire collection or retrieve individual member
    break;
  case 'PUT':       
    // Replace entire collection or member
    break;  
  case 'POST':      
    // Create new member
    break;
  case 'DELETE':    
    // Delete collection or member
    break;
}
echo json_encode($returnObject);

Sources: https://stackoverflow.com/a/897311/1766230 and http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services

Community
  • 1
  • 1
Luke
  • 18,811
  • 16
  • 99
  • 115
2

Another framework which has not been mentioned so far is Laravel. It's great for building PHP apps in general but thanks to the great router it's really comfortable and simple to build rich APIs. It might not be that slim as Slim or Sliex but it gives you a solid structure.

See Aaron Kuzemchak - Simple API Development With Laravel on YouTube and

Laravel 4: A Start at a RESTful API on NetTuts+

zimt28
  • 705
  • 2
  • 7
  • 20
2

I know that this question is accepted and has a bit of age but this might be helpful for some people who still find it relevant. Although the outcome is not a full RESTful API the API Builder mini lib for PHP allows you to easily transform MySQL databases into web accessible JSON APIs.

Brannon
  • 1,286
  • 2
  • 21
  • 36
0

As simon marc said, the process is much the same as it is for you or I browsing a website. If you are comfortable with using the Zend framework, there are some easy to follow tutorials to that make life quite easy to set things up. The hardest part of building a restful api is the design of the it, and making it truly restful, think CRUD in database terms.

It could be that you really want an xmlrpc interface or something else similar. What do you want this interface to allow you to do?

--EDIT

Here is where I got started with restful api and Zend Framework. Zend Framework Example

In short don't use Zend rest server, it's obsolete.

James Butler
  • 3,852
  • 1
  • 26
  • 38
  • If you are interested, I'll be posting something on my blog about getting started with ZF and RESTful web services with a complete working example. – James Butler Jan 15 '11 at 02:47