Appendix B. RESTClient class

Here is a simple RESTClient class that you can use to consume services.

The name of the PHP class is RESTClient. This class does not use any other framework and is based solely on basic PHP constructs. Hence you can easily use this class on its own without having to install any other framework. This would be useful if you want to just consume services using some lightweight PHP code.

We use a private variable in the PHP code to track whether to use CURL or not based on the availability of CURL in the PHP system installed.

private $with_curl;

While creating an instance of the client, the constructor of the class either chooses to use CURL if the CURL functions are available or else it would use fopen functions for communicating with the services.

public function __construct() {
if (function_exists("curl_init")) {
$this->with_curl = TRUE;
} else {
$this->with_curl = FALSE;
}
}

The RESTClient class has four member functions get, post, put, and delete to work with HTTP verbs GET, POST, PUT and DELETE respectively. While using these methods of the class we must pay attention to the parameters that each method takes.

get Method

The get member function of RESTClient class takes two parameters, the URL of the service and the request parameters.

public function get($url, $params) {

And it builds the request URL to include the request parameters.

$params_str = "?";
if (is_array($params)) {
foreach ($params as $key => $value) {
$params_str .= urlencode($key) . "=" . urlencode($value) . "&";
}
} else {
$params_str .= $params;
}
$url .= $params_str;

And if CURL is available, it would send a GET request using CURL.

if ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
$result = curl_exec($curl);
curl_close($curl);
}

We are already familiar with the constructs used in the above method that were discussed in Chapter 2.

If CURL is not available, we would be using fopen function to send the GET request and fetch the result.

} else {
$opts = array (
'http' => array (
'method' => "GET",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
"
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}

In here, we use the options to be used with the HTTP request such as the HTTP method GET and user agent header. We then create a context with those options and open the URL with fopen, using the context created.

post Method

The post method takes three parameters, the service URL, data to be posted and an optional third parameter that specifies the content type.

public function post($url, $data, $content_type = "application /x-www-form-urlencoded") {

If CURL is available, the given data would be posted to the given service URL.

if ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, Array (
"Content-Type: " . $content_type
));
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
$result = curl_exec($curl);
curl_close($curl);
}

We set the content type as an HTTP header. So if the user of the class provided a custom content type that would be reflected in the request sent to the service. Again, the CURL POST syntax used in this method was discussed in Chapter 2 in detail.

If CURL is not available, as in the case of get method, we use fopen to get the job done.

} else {
$opts = array (
'http' => array (
'method' => "POST",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
" .
"Content-Type: " . $content_type . "
" .
"Content-length: " . strlen($data
) . "
",
'content' => $data
));
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}

put Method

The put method takes two parameters, the service URL and data to be put to the service.

public function put($url, $data) {

While using PUT with CURL, we need to have a file handler with the data to be sent to service with PUT. So we create a file handler in memory first and then write the data given by the user to that file handler.

$fh = fopen('php://memory', 'rw');
fwrite($fh, $data);
rewind($fh);

Then we put that data to the service using CURL.

$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
curl_setopt($curl, CURLOPT_INFILE, $fh);
curl_setopt($curl, CURLOPT_INFILESIZE, strlen($data));
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_PUT, 1);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close($curl);
fclose($fh);

If CURL is not present, we again use fopen to handle the PUT request.

} else {
$opts = array (
'http' => array (
'method' => "PUT",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
" .
"Content-Type: " . $content_type . "
" .
"Content-length: " . strlen($data
) . "
",
'content' => $data
));
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}

delete Method

The delete method takes two parameters, the service URL and request parameters to be used with delete request to the service.

As in the case of GET requests, we use the request parameters and build the URL with the request parameters in place.

$params_str = "?";
if (is_array($params)) {
foreach ($params as $key => $value) {
$params_str .= urlencode($key) . "=" . urlencode($value) . "&";
}
} else {
$params_str .= $params;
}
$url .= $params_str;

Then if CURL is present, we send the DELETE request to the service URL with CURL.

if ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "delete");
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
$result = curl_exec($curl);
curl_close($curl);
}

If CURL is not present, we use the fopen logic.

} else {
$opts = array (
'http'=> array (
'method' => "DELETE",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
"
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}

Complete RESTClient Class

<?php
complete RESTClient classaboutclass RESTClient {
private $with_curl;
const USER_AGENT = 'RESTClient';
/*
* Constructor of the RESTClient
*/
public function __construct() {
if (function_exists("curl_init")) {
$this->with_curl = TRUE;
} else {
$this->with_curl = FALSE;
}
}
/*
* Call the HTTP 'GET' method
* @param string $url URL of the service.
* @param array $params request parameters, hash of (key,value) pairs
* @return response string
*/
public function get($url, $params) {
$params_str = "?";
if (is_array($params)) {
foreach ($params as $key => $value) {
$params_str .= urlencode($key) . "=" . urlencode($value) . "&";
}
} else {
$params_str .= $params;
}
$url .= $params_str;
$result = "";
complete RESTClient classaboutif ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($curl);
curl_close($curl);
} else {
$opts = array (
'http' => array (
'method' => "GET",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
"
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}
return $result;
}
/*
* Call the HTTP 'POST' method
* @param string $url URL of the service..
* @param string $data request data
* @param array $content_type the http content type
* @return response string
*/
public function post($url, $data, $content_type = "application /x-www-form-urlencoded") {
complete RESTClient classabout$result = "";
if ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, Array (
"Content-Type: " . $content_type
));
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
$result = curl_exec($curl);
curl_close($curl);
} else {
$opts = array (
'http' => array (
'method' => "POST",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
" .
"Content-Type: " . $content_type . "
" .
"Content-length: " . strlen($data
) . "
",
'content' => $data
));
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}
return $result;
complete RESTClient classabout}
/*
* Call the HTTP 'PUT' method
* @param string $url URL of the service..
* @param string $data request data
* @return response string
*/
public function put($url, $data) {
$result = "";
if ($this->with_curl) {
$fh = fopen('php://memory', 'rw');
fwrite($fh, $data);
rewind($fh);
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
curl_setopt($curl, CURLOPT_INFILE, $fh);
curl_setopt($curl, CURLOPT_INFILESIZE, strlen($data));
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_PUT, 1);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close($curl);
fclose($fh);
} else {
$opts = array (
'http' => array (
'method' => "PUT",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
" .
"Content-Type: " . $content_type . "
" .
"Content-length: " . strlen($data
) . "
",
'content' => $data
));
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}
return $result;
}
/*
complete RESTClient classabout* Call the HTTP 'DELETE' method
* @param string $url URL of the service..
* @param array $params request parameters, hash of (key,value) pairs
*/
public function delete($url, $params) {
$params_str = "?";
if (is_array($params)) {
foreach ($params as $key => $value) {
$params_str .= urlencode($key) . "=" . urlencode($value) . "&";
}
} else {
$params_str .= $params;
}
$url .= $params_str;
$result = "";
if ($this->with_curl) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "delete");
curl_setopt($curl, CURLOPT_USERAGENT, RESTClient :: USER_AGENT);
$result = curl_exec($curl);
curl_close($curl);
} else {
$opts = array (
'http' => array (
'method' => "DELETE",
'header' => "User-Agent: " . RESTClient :: USER_AGENT . "
"
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
complete RESTClient classabout}
}
}
?>

get Example

Let's use the RESTClient class to consume some services. Let us use the library example service from previous chapters first. Here is the PHP client code for getting the books.

<?php
require "RESTClient.php";
$client = new RESTClient();
$result = $client->get( "http://localhost/rest/09/library.php/book", array());
printf("Response = %s <br>", htmlspecialchars($result));
?>

First, we indicate that we require the source file with RESTClient PHP class. We use a require statement to do this. Obviously, we assume that the PHP class is defined in a file with the name RESTClient.php.

require "RESTClient.php";

Next we create an instance of the RESTClient class.

$client = new RESTClient();

And we send a GET request to the service URL.

$result = $client->get( "http://localhost/rest/09/library.php/book", array());

Note that the request parameters array is empty because we do not have any parameters to be sent to the service.

Finally we print out the result.

printf("Response = %s <br>", htmlspecialchars($result));

Note how the use of the RESTClient class has simplified our PHP code to consume the service a great deal.

post Example

Let's also look at how to use RESTClient class for a POST request with the library service.

<?php
require "RESTClient.php";
$data = <<<XML
<books>
<book><name>Book7</name><author>Auth7</author><isbn>ISBN0007</isbn></book>
<book><name>Book8</name><author>Auth8</author><isbn>ISBN0008</isbn></book>
</books>
XML;
$client = new RESTClient();
$client->post("http://localhost/rest/09/library.php/book", $data, "text/xml");
?>

As in the case of the sample used to GET data, the POST sample is very simple. First require the PHP file with the class implementation.

require "RESTClient.php";

Then we define the data that we want to be posted to the service.

$data = <<<XML
<books>
<book><name>Book7</name><author>Auth7</author><isbn>ISBN0007</isbn></book>
<book><name>Book8</name><author>Auth8</author><isbn>ISBN0008</isbn></book>
</books>
post methodexampleXML;

Next, create the RESTClient class instance.

$client = new RESTClient();

And post the data to the service.

$client->post("http://localhost/rest/09/library.php/book", $data, "text/xml");

Note that we have used the third parameter with the value text/xml to indicate that we are posting XML data to the service.

Yahoo Search Client Example

Let's see how to use RESTClient class to consume the Yahoo spelling suggestion service.

<?php
require "RESTClient.php";
$client = new RESTClient();
$result = $client->get(
"http://search.yahooapis.com/WebSearchService/V1/
spellingSuggestion",
array( "appid" => "YahooDemo",
"query" => "apocalipto"));
printf("Response = %s <br>", htmlspecialchars($result));
?>

First we require the PHP file with the class implementation.

require "RESTClient.php";

Next, create the RESTClient class instance.

$client = new RESTClient();

And send the GET request to the service.

$result = $client->get(
"http://search.yahooapis.com/WebSearchService/V1/
spellingSuggestion",
array( "appid" => "YahooDemo",
"query" => "apocalipto"));

Note that in addition to the service location URL, used as the first parameter, we have used the service request parameters as an array in the second parameter.

Summary

In this chapter, we introduced a PHP class named RESTClient that can be used to consume REST style services. This class supports all key HTTP verbs, GET, POST, PUT and DELETE.

The advantage of using such a class is that it minimizes the complexity of your client code. At the same time you can re-use this class for all your REST style client implementations. This PHP class is sufficient for most simple REST style client programs and requires no third-party libraries. However, if you want to implement services and also want advanced clients, it is advised that you use more established framework such as Zend Framework or WSO2

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset