PHP Rest Server (part 1 of 3)

I recently had reason to write a REST server in PHP, which was very interesting. There aren't a whole lot of resources on this topic around so I thought I'd write an outline of what I did. There is quite a lot to it so I'm publishing in multiple sections - this is part 1, which covers the central functionality and handling the incoming request.

Wrapping an Existing Class

The main functionality of the service was written in a class that had no awareness that it was a service - this is a similar approach to the one I described when I wrote about the PHP Soap Server - start with a normal functioning class and write some unit tests for it. The example I'm using today looks like this (my real version actually connects to the database and stuff but this is a nice mock of passing in a number and getting back an array):

class Library {
    public function getUserDetails($user_id) {
        $details = array(
            "user_id" => $user_id,
            "name" => 'Joe Bloggs',
            "email" => 'joe@example.com');
        return $details;
    }
}

In the soap article, you can see that wrapping a class takes just a few lines - for REST more code is required, but the idea is completely the same. In actual fact we started out with this as a soap service but then it was switched to rest - I only had to re-write the wrapper stuff and not any of the core functionality. Using the wrapper approach would also allow services to be published in multiple ways with the same underlying codebase.

Incoming Requests - Intialising the Wrapper

First of all I wrote a .htaccess file to direct all requests to the one controller file - so that all the different URLs would be handled in the same way.

As the requests came into here, I grabbed the data I needed and initialised the service class, something like this:

$service = new Rest_Service();
// instantiate the main functional class and pass to service
$library = new Library();
$service->setLibrary($library);
// create a response object and pass to service
$response = new Response();
$service->setResponse($response);
 
// set up some useful variables
$service->url = $_SERVER['REQUEST_URI'];
$service->method = $_SERVER['REQUEST_METHOD'];
$service->getArgs = $_GET;
$service->postArgs = $_POST;
parse_str(file_get_contents('php://input'), $service->putArgs);
parse_str(file_get_contents('php://input'), $service->deleteArgs);
 
$service->handle();

The variables are all read here and passed in to help decouple the systems - doing it this way allows us to initialise the Service with different incoming variables and/or a different library which can be really useful when testing, as it allows isolation of individual components. The syntax for getting the put and delete data is an interesting one, I wrote about this already in my post on accessing incoming PUT data from PHP, there are some helpful comments on that post as well.

To be continued ... later parts will cover the service itself and the response format used.

14 thoughts on “PHP Rest Server (part 1 of 3)

  1. Looks good Lorna, I have been doing something fairly similar. I don't know about you but I found that following the REST pattern wrote a lot of the code itself.

    I'm not sure if you did this or not, but I found it beneficial to abstract the request into an interface and then do something like:

    $service->handle($request)

    Gives you a little extra flexibility.

    I'm curious about how you handle responses, looks like you're doing things a little differently to me, so looking forward to your next post.

  2. Have you seen the article in php|architect on creating a service with the Reflection API?

    http://c7y.phparch.com/c/entry/1/art,rest_with_reflection/1

    (Seems like a lot of people have had a go at this problem--I've written something similar as well. In my case it turned out to be really convenient to pull the method name from the "filename" of the URL, and the output type (JSON, text, debug) from the "extension" part of the URL.)

    There's also:

    http://framework.zend.com/manual/en/zend.rest.server.html

  3. This is part 2 of my rest service writing article. In part 1 we saw the library which holds the functionality we will be using, and we also handled the incoming request and captured all the data we'll be using.

    The REST Service

    This is not really t

  4. Rory: I didn't abstract the request object but it would be a nice separation to do so.

    Michael: I haven't read that but I will, thanks for the link. Calling formulaic method names seems to a feature of most implementations I've seen so far. I haven't looked at the Zend Framework stuff - the application for this service is high-availability enough to keep us away from frameworks of any kind, purely for performance reasons.

  5. This is part 3 of my article about writing a restful service server. If you haven't already, you might like to read part 1 (covering the core library and grabbing the information we need from the incoming request) and part 2 (covering the service handle

  6. Thanks Lorna. Some time ago I wanted to build a service or something to provide data to my application, but I didn't know where to start. I think your approach and implementation is very valuable and useful. Thanks again!!

    • Lorna, nice into!

      Question, I read all 3 parts, and still not get where do you defined Rest_Service()?

      Or I'm blind were :)

      Thanks

      • NC: it isn't actually very clear (I must update this tutorial some time), the Rest_Service class contains the methods defined in Part 2 ... hope that helps!

  7. hi Lorna, really good article, thank you.
    I'm looking to implement a rest server in php and it would be very nice if you could explain more about the .htaccess file. I can't find any simple help about that kind of file.
    Thx in advance

  8. hi Lorna,

    great post. I'm looking to use php web services and the REST server model for my own windows desktop application which will use the web service to authenticate the user. Will reduce piracy. I like your approach because it's lean and mean. I've been wrtining software for over 20 years now and I totally agree with you that frames are great but for performance it's best to creatye something lite weight!

    Nitin

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>