How To: Making a PHP REST client to call REST resources
A lot of companies these days (including Amazon and Yahoo!) are exposing their web services in the form of REST resources. At a high level REST is pretty easy to understand, all you’re doing is exposing a web service in the form of a URL. Users can then query this URL, through HTTP methods like GET and POST. REST calls generally return some type of XML or Object Encoding like JSON.
An example would be Yahoo!’s Geocoding API, with the following URL:
http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=701+First+Street&city=Sunnyvale&state=CA
I would get:
<Result precision="address">
<Latitude>37.416384</Latitude>
<Longitude>-122.024853</Longitude>
<Address>701 FIRST AVE</Address>
<City>SUNNYVALE</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result>
So Yahoo! exposes the Geocode URL and allows you to query this resource using URL parameters like appid and street. Dynamically building your URL to query a given resource is OK, generally that’s what people do, like the following:
$base = 'http://xml.amazon.com/onca/xml3';
$query_string = "";
$params = array( 'ManufacturerSearch' => "O'Reilly",
'mode' => 'books',
'sort' => '+salesrank',
'page' => 1,
'type' => 'lite',
'f' => 'xml',
't' => 'trachtenberg-20' ,
'dev-t' => 'XXXXXXXXXXXXXX' ,
);
foreach ($params as $key => $value) {
$query_string .= "$key=" . urlencode($value) . "&";
}
$url = "$base?$query_string";
$output = file_get_contents($url);
The problem here, is that REST is meant to take advantage of HTTP methods GET, POST, PUT, DELETE, etc.. When people are showing examples which dynamically build queries and call file_get_contents, the average user doesn’t appreciate (understand) what type of request is being made. Do they care? Should they care? We’ll that’s another story. Eventually though, more intense REST resources will become widely available, and it will be critical the user (developer) understands if their making a POST or PUT request.
I came across a great PEAR package the other day called HTTP_REQUEST, which among many things supports GET/POST/HEAD/TRACE/PUT/DELETE, basic authentication, proxy, proxy authentication, SSL, file uploads and more. Using this package, I got started on a simple wrapper class called RESTclient, which gives intuitive support for making REST resource calls.
So if I was going to use RESTclient to call the Geocode API above, it would look like this:
<?php
require_once "RESTclient.php";
$rest = new RESTclient();
$inputs = array();
$inputs["appid"] = "YahooDemo";
$inputs["street"] = "701 First Street";
$inputs["city"] = "Sunnyvale";
$inputs["state"] = "CA";
$url = "http://api.local.yahoo.com/MapsService/V1/geocode/"
$rest->createRequest("$url","POST",$inputs);
$rest->sendRequest();
$output = $rest->getResponse();
echo $output;
?>
At this point, you might be thinking, who cares — what’s the difference between using a loop to dynamically generate the URL or RESTclient. There are lots of reasons, first off, I can easily call the Geocode resource again using another address just by changing:
$inputs["street"] = "1600 Amphitheatre Parkway";
$inputs["city"] = "Mountain View";
There was no need to re-generate the URL. Furthermore, I’m explicitly specifying a POST request. Just as easily I can make a PUT, DELETE, etc. request on a given resource by changing the createRequest method parameters.
The class below is RESTclient. Note, I put this together to prove a point, it still needs some work if you plan on using it.
<?php
require_once "HTTP/Request.php";
class RESTClient {
private $root_url = "";
private $curr_url = "";
private $user_name = "";
private $password = "";
private $response = "";
private $responseBody = "";
private $req = null;
public function __construct($root_url = "", $user_name = "", $password = "") {
$this->root_url = $this->curr_url = $root_url;
$this->user_name = $user_name;
$this->password = $password;
if ($root_url != "") {
$this->createRequest("GET");
$this->sendRequest();
}
return true;
}
public function createRequest($url, $method, $arr = null) {
$this->curr_url = $url;
$this->req =& new HTTP_Request($url);
if ($this->user_name != "" && $this->password != "") {
$this->req->setBasicAuth($this->user_name, $this->password);
}
switch($method) {
case "GET":
$this->req->setMethod(HTTP_REQUEST_METHOD_GET);
break;
case "POST":
$this->req->setMethod(HTTP_REQUEST_METHOD_POST);
$this->addPostData($arr);
break;
case "PUT":
$this->req->setMethod(HTTP_REQUEST_METHOD_PUT);
// to-do
break;
case "DELETE":
$this->req->setMethod(HTTP_REQUEST_METHOD_DELETE);
// to-do
break;
}
}
private function addPostData($arr) {
if ($arr != null) {
foreach ($arr as $key => $value) {
$this->req->addPostData($key, $value);
}
}
}
public function sendRequest() {
$this->response = $this->req->sendRequest();
if (PEAR::isError($this->response)) {
echo $this->response->getMessage();
die();
} else {
$this->responseBody = $this->req->getResponseBody();
}
}
public function getResponse() {
return $this->responseBody;
}
}
?>

November 23rd, 2006 at 4:35 am
Does any one know of similar client for J2ME pl.
October 23rd, 2007 at 10:56 am
Thanks; there is a little bug in your test code at this line :
$url = “http://api.local.yahoo.com/MapsService/V1/geocode/”
you forgot the tailing “;”.
$url = “http://api.local.yahoo.com/MapsService/V1/geocode/” ;
I have a question: how can I find the target site has or has not this service, and how you find out REST of Amazon and Yahoo?
Please response me soon,I’m waiting!
Thanks
November 20th, 2007 at 12:42 pm
Hi Ghassem,
Sorry for the delay in responding, I get so much spam on this blog now that it’s hard to stay on top of these things. The only way to know if the site supports REST is to take a look at their developer areas. For example at Yahoo for PHP it would be this page and at Amazon this page.
Good luck,
George
December 8th, 2007 at 9:08 am
Hi george i was going thru ur blog….
Just want to make a suggestion regarding ur spam concern in ur blog… use
December 8th, 2007 at 9:09 am
Akismet
http://www.akismet.com
December 9th, 2007 at 3:50 pm
Hi Manuj,
Thanks for the tip, I have Akismet turned on and it catches a lot of the spam, but still stuff gets through.
Talk to you soon,
George
April 10th, 2008 at 5:55 am
thanks, very useful.
I need to upload a file to REST Server, How can i do that using RESTClient class
May 8th, 2008 at 5:38 pm
Nice article, I’m englued into a SOAP client/server and as services start to get more and more complex I think I’ll migrate to REST (before it’s too late…).
> Logu :
You could create a POST or PUT request, sending 2 or 3 variables for your file : file name, mime type (optionally), and a base64_encode of the file itself (retreived using file_get_contents for example)
Then on the serverside you will need to create a new file with the specified name and write into it the base64_decode of the sent variable.
August 13th, 2008 at 12:14 am
wew, great article.
I need to know more about REST, could you please help me. How do I know the response is from yahoo api ??
I’ve try it, but I got no result than err…
thanks
August 13th, 2008 at 12:21 am
could you please give me HTTP/Request.php library…
I don’t have it… Or where should I can find it..
thanks
August 27th, 2008 at 8:08 am
hi!
can you tell me more about REST…
i dont have enough knowledge about it..
September 16th, 2008 at 10:24 am
hi
i don’t have enough knowledge about rest.
please can u tell me how to connect through a MySQL server which can ONLY be accessed from the REST server.
regards
rohit
September 29th, 2008 at 9:21 am
you can also use stream_context_create() to set the method for the request.
example:
$postdata=http_build_query(Array(’can’=>’pippo’,'pesce’=>’palla’));
$opts= Array ( ‘http’=>Array(
‘method’=>’POST’,
‘header’ => ‘Content-type: application/x-www-form-urlencoded’,
‘content’=>$postdata
));
$resource=stream_context_create($opts);
file_get_contents(”http://localhost/example/post.php”, false, $resource);
October 22nd, 2008 at 11:45 am
I like to use cURL in php for connecting to REST services. Simply call the URI and then use simpleXML to parse the response. simple, takes less than 15 lines to get a very simple client to work.
October 22nd, 2008 at 12:11 pm
The function i use to access REST services
October 22nd, 2008 at 12:12 pm
// PHP Functions needed to access various APIs
function get_REST_xml($uri, $rawXML = 0)
{
global $parsed;
global $uri;
$getXML = curl_init() or die(curl_error()); // initialize curl handle
curl_setopt($getXML, CURLOPT_URL,$uri); // set url to post to
curl_setopt($getXML, CURLOPT_FAILONERROR, 1);
curl_setopt($getXML, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
curl_setopt($getXML, CURLOPT_RETURNTRANSFER,1); // return into a variable
// curl_setopt($getXML, CURLOPT_SSL_VERIFYHOST, 2);
// curl_setopt($getXML, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($getXML , CURLOPT_HEADER, 0);
curl_setopt($getXML, CURLOPT_TIMEOUT, 3); // times out after 4s
// curl_setopt($getXML,CURLOPT_POST,1); // Set the method as post
// curl_setopt($getXML, CURLOPT_POSTFIELDS, "key=".$API_key);
$pulledXML = curl_exec($getXML);
//echo ("");
//print_r(curl_getinfo($getXML));
//echo ("");
// echo "\n\ncURL error number:" .curl_errno($getXML);
// echo "\n\ncURL error:" . curl_error($getXML);
// ...close cURL handle ($getXML) below
curl_close($getXML);
if ($rawXML == 0)
{
$parsed = simplexml_load_string($pulledXML);
return $parsed;
}
elseif($rawXML == 1)
{
return $pulledXML;
}
else
{
echo "Function Error";
}
}
February 5th, 2009 at 8:38 am
hallo,
can somebody help me to consum a webservice using php curl and xerces with data from MySQL…I am a newby but i make it subjectif “learning by doing”
thanks a lot
February 5th, 2009 at 8:41 am
Sorry I wanna mean how many script shall I write for this action! Request Response and parsing with xerces.
Thanx
June 14th, 2009 at 5:57 pm
There is a great Eclipse plugin where you can visually construct your REST call: http://http4e.roussev.org/
Of course this is not an PHP client, yet it is very priceless tool for REST and HTTP.
November 25th, 2009 at 1:06 pm
how rest work with this kind of uris … http://api.local.yahoo.com/MapsService/V1/geocode?appis without extension… it sounds more familiar
http://api.local.yahoo.com/MapsService/V1/geocode.php?appis
thanks
December 28th, 2009 at 9:21 am
Hi,
can anyone help me in using REST.
Lets say i have link (http://dev.ss-build.com/server2/services/application.wadl).
It have a method
How can i access or use or call this method .
Now, let us say i have created a php page containing form where i will enter my email and password.
now when i click on login after entering my mail and password.
It should use this method and we can say a session will start and i will able to acess the other page.
Now can any one tell me how can i do this??
What should i write in ACTION
please give a example.
December 28th, 2009 at 9:24 am
this is the method > loginForm
what should i write in form action means in .. .action=”???” m
December 30th, 2009 at 1:54 pm
George, excellent article. However, I’m trying to begin writing my own lightweight REST class for use with Amazon Web Services, but I’m confused by one thing in your class:
require_once “RESTclient.php”;
Is this line just assuming that we have *some REST client* to use? Which one would you recommend using? I only need to send GET requests for the time being. If you could reply to this, it’d be much appreciated :)
Thanks man,
-Geddy
January 22nd, 2010 at 6:47 am
I want to know what is the content of file HTTP/Request.php.
What is in this file?
February 3rd, 2010 at 11:23 pm
http://pear.php.net/package/HTTP_Request/
The author mentioned this pear package above.
I hope this helps.
Within the next days I’ll try it out.
Regards
otto06217