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.
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.
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); }
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); }
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); }
<?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} } } ?>
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.
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.
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.
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