Book Image

RESTful PHP Web Services

By : Samisa Abeysinghe
Book Image

RESTful PHP Web Services

By: Samisa Abeysinghe

Overview of this book

<p>Representational State Transfer (REST) is a form of software architecture; systems that follow it are often called RESTful. It is the architectural style that drives the World Wide Web (the motivation for REST was to capture elements that made the Web successful), and RESTful web services use simple protocols already familiar to web developers. RESTful web services are found in lots of places with big name Web APIs such as Flickr, and Yahoo search following a REST-based approach.<br /><br />With any architectural style or approach, struggling with its basic concepts is just one problem – implementation in your favorite language is another, and that's where this book comes in. If you're a PHP developer, this book will show you how to create and consume RESTful web services in PHP, and make your services work well in the context of the Web.<br /><br />You will learn about the basic concepts of REST, and then look at PHP tools, libraries and techniques for working with RESTful web services. You will see how to use other RESTful services from your PHP applications, and also how to engineer your PHP applications to make them RESTful.<br /><br />This book is about implementing RESTful web services in PHP, and so the book is packed with example code and careful explanations.</p>
Table of Contents (15 chapters)
RESTful PHP Web Services
Credits
About the Author
About the Reviewers
Preface
Index

Implementing Services


There is a PHP class named WSService that comes with WSO2 WSF/PHP.

When you are implementing a service, you need to provide the set of operations and the set of REST semantics, including HTTP method and resource location.

Let's see how we can implement the book resource of the library system sample with WSO2 WSF/PHP.

$service = new WSService(array (
    "operations" => $operations,
    "RESTMapping" => $restmap
));

$service->reply();

Operations and REST map are arrays provided to the service. The call to reply() method indicates that the service should go ahead and process the request.

Here is the operations array.

$operations = array (
    "getBooks" => "getBooksFunction",
    "addBooks" => "addBooksFunction"
);

What we are doing here is that we map service operations to PHP functions that implement those operations. As an example, the getBooks operation would be handled by a function with the name getBooksFunction, defined in the PHP script. Note that these functions can take parameters, which we will see later in this chapter. However, when we define the options array, it is not required to mention the parameters of the functions. It is sufficient to mention only the name of the function irrespective of the type or number of parameters the functions would be accepting.

Here is the REST mapping array.

$restmap = array (
    "getBooks" => array (
        "HTTPMethod" => "GET",
        "RESTLocation" => "book"
    ),
    "addBooks" => array (
        "HTTPMethod" => "POST",
        "RESTLocation" => "book"
    )
);

In here, we are providing the REST characteristics for the operations. As an example we specify that the getBooks operation would only respond to the GET requests and addBooks would respond to the POST requests. And both these operations are mapped to the location book. If the name of the PHP script with the service implementation is library.php and located in the folder /rest/09, the resource URL would be http://localhost/rest/09/library.php/book. As we saw in Chapter 4, while designing the sample Library service, a given business operation on a given resource does not get mapped to more than one HTTP verb. Hence in the operation mapping array more than one operation can be mapped to the same resource URL but with different HTTP verbs.

This design nicely maps to the resource design that we looked at while discussing the library system in Chapter 5.

URI

HTTP Method

Collection

Operation

Business Operation

/book

GET

books

retrieve

Get books

/book

POST

books

create

Add book(s)

In the implementation, we can cleanly map the resource location URI, the HTTP method required and the business operation.

Here is the getBooksFunction.

function getBooksFunction($inMessage) {
    $link = mysql_connect('localhost', 'sam', 'pass') or die('Could not connect: ' . mysql_error());
    mysql_select_db('library') or die('Could not select database');

    $query = "SELECT b.id, b.name, b.author, b.isbn FROM book as b";

    $result = mysql_query($query) or die('Query failed: ' . mysql_error());
    $response = "<books>";
    while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
        $response .= "<book>";
        foreach ($line as $key => $col_value) {
            $response .= "<$key>$col_value</$key>";
        }
        $response .= "</book>";
    }
    $response .= "</books>";
    mysql_free_result($result);
    mysql_close($link);
    $outMessage = new WSMessage($response);
    return $outMessage;
}

In here, we are not interested in the input parameter as we are not expecting any. However, the operation function syntax mandates to have one, as the framework would fill in that if there were any input.

The response building logic should look familiar to you. We connect to the database, query for the book information and prepare the response XML string.

Finally, in this function, we create an instance of WSMessage with the response XML string that we prepared and returned.

    $outMessage = new WSMessage($response);
    return $outMessage;

If there is a return value, it is expected by the framework that you always return a WSMessage instance from the function implementing the operation business logic.

Next, the add book operation.

function addBooksFunction($inMessage) {
    $link = mysql_connect('localhost', 'sam', 'pass') or die('Could not connect: ' . mysql_error());
    mysql_select_db('library') or die('Could not select database');
    $xml = simplexml_load_string($inMessage->str);
    foreach ($xml->book as $book) {
        $query = "INSERT INTO book (name, author, isbn) VALUES ('$book->name', '$book->author', '$book->isbn')";
        $result = mysql_query($query) or die('Query failed: ' . mysql_error());
        mysql_free_result($result);
    }
    mysql_close($link);
    return;
}

In this operation, we pick the incoming XML request from the in message.

    $xml = simplexml_load_string($inMessage->str);

Note that $inMessage is an instance of WSMessage class. WSMessage class captures the incoming XML request as a string and stores it in the str member variable.

And then create new book instances in the database which you are already familiar with.

Here is the complete PHP source code for the service.

<?php
function getBooksFunction($inMessage) {
    $link = mysql_connect('localhost', 'sam', 'pass') or die('Could not connect: ' . mysql_error());
    mysql_select_db('library') or die('Could not select database');
    $query = "SELECT b.id, b.name, b.author, b.isbn FROM book as b";
    $result = mysql_query($query) or die('Query failed: ' . mysql_error());
    $response = "<books>";
    while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
        $response .= "<book>";
        foreach ($line as $key => $col_value) {
            $response .= "<$key>$col_value</$key>";
        }
        $response .= "</book>";
    }
    $response .= "</books>";
    mysql_free_result($result);
    mysql_close($link);
    $outMessage = new WSMessage($response);
    return $outMessage;
}
function addBooksFunction($inMessage) {
    $link = mysql_connect('localhost', 'sam', 'pass') or die('Could not connect: ' . mysql_error());
    mysql_select_db('library') or die('Could not select database');
    $xml = simplexml_load_string($inMessage->str);
    foreach ($xml->book as $book) {
        $query = "INSERT INTO book (name, author, isbn) VALUES ('$book->name', '$book->author', '$book->isbn')";
        $result = mysql_query($query) or die('Query failed: ' . mysql_error());
        mysql_free_result($result);
    }
    mysql_close($link);
    return;
}
$operations = array (
    "getBooks" => "getBooksFunction",
    "addBooks" => "addBooksFunction"
);
$restmap = array (
    "getBooks" => array (
        "HTTPMethod" => "GET",
        "RESTLocation" => "book"
    ),
    "addBooks" => array (
        "HTTPMethod" => "POST",
        "RESTLocation" => "book"
    )
);
$service = new WSService(array (
    "operations" => $operations,
    "RESTMapping" => $restmap
));
$service->reply();
?>