351

Our client had given me a REST API to which I need to make a PHP call to. But as a matter of fact the documentation given with the API is very limited, so I don't really know how to call the service.

I've tried to Google it, but the only thing that came up was an already expired Yahoo! tutorial on how to call the service. Not mentioning the headers or anything in depth information.

Is there any decent information around how to call a REST API, or some documentation about it? Because even on W3schools, they only describes the SOAP method. What are different options for making rest API in PHP?

Jonas
  • 97,987
  • 90
  • 271
  • 355
Michiel
  • 7,213
  • 16
  • 57
  • 110

12 Answers12

488

You can access any REST API with PHPs cURL Extension. However, the API Documentation (Methods, Parameters etc.) must be provided by your Client!

Example:

// Method: POST, PUT, GET etc
// Data: array("param" => "value") ==> index.php?param=value

function CallAPI($method, $url, $data = false)
{
    $curl = curl_init();

    switch ($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            break;
        default:
            if ($data)
                $url = sprintf("%s?%s", $url, http_build_query($data));
    }

    // Optional Authentication:
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($curl, CURLOPT_USERPWD, "username:password");

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    $result = curl_exec($curl);

    curl_close($curl);

    return $result;
}
Christoph Winkler
  • 5,800
  • 1
  • 15
  • 17
  • As far as I can see in the documentation, they are provided. Do you happen to have some documentation about it? – Michiel Mar 21 '12 at 10:38
  • Thanks Christoph, but where do I place the authentication headers? – Michiel Mar 21 '12 at 14:10
  • @Michiel I updated my example with a basic Authentication. See the Parameters Section for [curl_setopt](http://de.php.net/manual/en/function.curl-setopt.php) for other Authentication options. – Christoph Winkler Mar 21 '12 at 14:19
  • Thanks! I'll test it in a minute. – Michiel Mar 21 '12 at 15:06
  • So, when calling the function I should get the returned value? – Michiel Mar 21 '12 at 15:47
  • Just one thing that's not clear to me... What do you mean by the `method`? – Michiel Mar 21 '12 at 16:11
  • 1
    @Michiel: The HTTP Request Method (GET, POST, PUT etc.). Depending on the API there are different methods required. i.e. GET for reading, POST for writing. – Christoph Winkler Mar 22 '12 at 07:17
  • 2
    @Michiel `$data` is an associative array (data[fieldname] = value) which holds the data sent to the api method. – Christoph Winkler Mar 22 '12 at 09:12
  • 1
    Thanks for your great assistance! – Michiel Mar 23 '12 at 10:36
  • 2
    Note, the [`curl_close`](http://php.net/manual/en/function.curl-close.php) function is not called, what could cause extra memory consumption if the CallAPI function is called repeatedly. – Bart Verkoeijen Jul 22 '14 at 08:19
  • @BartVerkoeijen Thanks! Updated my answer. – Christoph Winkler Jul 22 '14 at 09:00
  • @ChristophWinkler I need to call API (URL) and when I see the code of the API, it has `window.location` in it. So when I call API, the page will be redirected to the next page with wrong app folder. how do I proceed? – UserProg Apr 14 '15 at 07:32
  • @UserProg `window.location` is a JavaScript function so it shouldn't affect cURL. – Christoph Winkler Apr 14 '15 at 08:50
  • @ChristophWinkler my attempt was unsuccessful but I will try again. By the way this is my question http://stackoverflow.com/questions/29618842/php-api-call-url-api-redirects-to-different-page-but-i-need-to-be-on-same-pa – UserProg Apr 14 '15 at 09:30
  • @ChristophWinkler I have tried it using cURL and still the my page is redirected automatically. – UserProg Apr 14 '15 at 09:41
  • 2
    The answer from @colan below is way better - it saves you the whole hassle with building your own error handling and wrapper methods. – Andreas Nov 10 '16 at 11:08
  • 1
    For some reason this only worked once I `json_encode($data)`. – Neurotransmitter Dec 04 '17 at 19:59
  • 1
    @TranslucentCloud true and I also had to set `CURLOPT_HTTPHEADER` to `array('Content-Type: application/json', 'Accept: application/json');` – Fanky May 11 '19 at 14:43
211

If you have a url and your php supports it, you could just call file_get_contents:

$response = file_get_contents('http://example.com/path/to/api/call?param1=5');

if $response is JSON, use json_decode to turn it into php array:

$response = json_decode($response);

if $response is XML, use simple_xml class:

$response = new SimpleXMLElement($response);

http://sg2.php.net/manual/en/simplexml.examples-basic.php

Andreas Wong
  • 55,398
  • 19
  • 100
  • 120
  • 33
    If the REST endpoint returns an HTTP error status (e.g. 401), the `file_get_contents` function fails with a warning and returns null. If the body contains an error message, you cannot retrieve it. – Bart Verkoeijen Jul 22 '14 at 08:08
  • 4
    Its main drawback is that your PHP installation must have fopen wrappers enabled in order to access URLs. If fopen wrappers is not enabled, you will not be able to use file_get_contents for Web services requests. – Oriol Feb 16 '15 at 01:41
  • 2
    fopen wrappers are among the parts of PHP now seen as a vulnerability, so you're likely to see some hosts disable it. – Marcus Downing Mar 29 '18 at 09:22
168

Use Guzzle. It's a "PHP HTTP client that makes it easy to work with HTTP/1.1 and takes the pain out of consuming web services". Working with Guzzle is much easier than working with cURL.

Here's an example from the Web site:

$client = new GuzzleHttp\Client();
$res = $client->get('https://api.github.com/user', [
    'auth' =>  ['user', 'pass']
]);
echo $res->getStatusCode();           // 200
echo $res->getHeader('content-type'); // 'application/json; charset=utf8'
echo $res->getBody();                 // {"type":"User"...'
var_export($res->json());             // Outputs the JSON decoded data
colan
  • 2,508
  • 1
  • 17
  • 17
  • 24
    Whoever is still using cURL has never taken a close look at this option. – JoshuaDavid Sep 04 '15 at 16:57
  • 1
    Seems nice. But what about fetching PNGs? For map tiles. I can only find JSON data mentioned at the web page you linked. – Henrik Erlandsson Oct 11 '18 at 12:33
  • @HenrikErlandsson, a quick google search revealed what seems to be a decent solution. https://stackoverflow.com/questions/55881436/how-to-get-and-display-an-image-from-a-guzzle-request – ChrisH Feb 02 '21 at 15:44
23

CURL is the simplest way to go. Here is a simple call

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "THE URL TO THE SERVICE");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, POST DATA);
$result = curl_exec($ch);


print_r($result);
curl_close($ch);
Broncha
  • 3,684
  • 1
  • 20
  • 34
16

Use HTTPFUL

Httpful is a simple, chainable, readable PHP library intended to make speaking HTTP sane. It lets the developer focus on interacting with APIs instead of sifting through curl set_opt pages and is an ideal PHP REST client.

Httpful includes...

  • Readable HTTP Method Support (GET, PUT, POST, DELETE, HEAD, and OPTIONS)
  • Custom Headers
  • Automatic "Smart" Parsing
  • Automatic Payload Serialization
  • Basic Auth
  • Client Side Certificate Auth
  • Request "Templates"

Ex.

Send off a GET request. Get automatically parsed JSON response.

The library notices the JSON Content-Type in the response and automatically parses the response into a native PHP object.

$uri = "https://www.googleapis.com/freebase/v1/mqlread?query=%7B%22type%22:%22/music/artist%22%2C%22name%22:%22The%20Dead%20Weather%22%2C%22album%22:%5B%5D%7D";
$response = \Httpful\Request::get($uri)->send();

echo 'The Dead Weather has ' . count($response->body->result->album) . " albums.\n";
Somnath Muluk
  • 46,917
  • 28
  • 204
  • 217
  • I am trying to use HTTPFUL as a solution and I am not sure if it can parse the json like `$condition = $response->weather[0]->main;` unless I am just doing the PHP side wrong – weteamsteve Jan 14 '20 at 01:16
12

You will need to know if the REST API you are calling supports GET or POST, or both methods. The code below is something that works for me, I'm calling my own web service API, so I already know what the API takes and what it will return. It supports both GET and POST methods, so the less sensitive info goes into the URL (GET), and the info like username and password is submitted as POST variables. Also, everything goes over the HTTPS connection.

Inside the API code, I encode an array I want to return into json format, then simply use PHP command echo $my_json_variable to make that json string availabe to the client.

So as you can see, my API returns json data, but you need to know (or look at the returned data to find out) what format the response from the API is in.

This is how I connect to the API from the client side:

$processed = FALSE;
$ERROR_MESSAGE = '';

// ************* Call API:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.myapi.com/api.php?format=json&action=subscribe&email=" . $email_to_subscribe);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS,"username=myname&password=mypass");   // post data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
curl_close ($ch);

// returned json string will look like this: {"code":1,"data":"OK"}
// "code" may contain an error code and "data" may contain error string instead of "OK"
$obj = json_decode($json);

if ($obj->{'code'} == '1')
{
  $processed = TRUE;
}else{
  $ERROR_MESSAGE = $obj->{'data'};
}

...

if (!$processed && $ERROR_MESSAGE != '') {
    echo $ERROR_MESSAGE;
}

BTW, I also tried to use file_get_contents() method as some of the users here suggested, but that din't work well for me. I found out the curl method to be faster and more reliable.

Brane
  • 2,781
  • 2
  • 31
  • 51
Derek Gogol
  • 1,198
  • 15
  • 15
5

You can use file_get_contents to issue any http POST/PUT/DELETE/OPTIONS/HEAD methods, in addition to the GET method as the function name suggests.

How to post data in PHP using file_get_contents?

Brane
  • 2,781
  • 2
  • 31
  • 51
Chuan Ma
  • 9,058
  • 2
  • 40
  • 34
  • 1
    file_get_content is realy bad idea when it comes to API. https://stackoverflow.com/questions/13004805/file-get-contents-or-curl-in-php/24954327 You can set custom method like file_get_contents_curl and use it instead of plain php solution.https://stackoverflow.com/questions/8540800/how-to-use-curl-instead-of-file-get-contents – Eryk Wróbel Jan 30 '20 at 14:43
5

as @Christoph Winkler mentioned this is a base class for achieving it:

curl_helper.php

// This class has all the necessary code for making API calls thru curl library

class CurlHelper {

// This method will perform an action/method thru HTTP/API calls
// Parameter description:
// Method= POST, PUT, GET etc
// Data= array("param" => "value") ==> index.php?param=value
public static function perform_http_request($method, $url, $data = false)
{
    $curl = curl_init();

    switch ($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            break;
        default:
            if ($data)
                $url = sprintf("%s?%s", $url, http_build_query($data));
    }

    // Optional Authentication:
    //curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    //curl_setopt($curl, CURLOPT_USERPWD, "username:password");

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    $result = curl_exec($curl);

    curl_close($curl);

    return $result;
}

}

Then you can always include the file and use it e.g.: any.php

    require_once("curl_helper.php");
    ...
    $action = "GET";
    $url = "api.server.com/model"
    echo "Trying to reach ...";
    echo $url;
    $parameters = array("param" => "value");
    $result = CurlHelper::perform_http_request($action, $url, $parameters);
    echo print_r($result)
d1jhoni1b
  • 5,891
  • 1
  • 42
  • 32
5

There are plenty of clients actually. One of them is Pest - check this out. And keep in mind that these REST calls are simple http request with various methods: GET, POST, PUT and DELETE.

Blu
  • 3,836
  • 6
  • 33
  • 61
deadrunk
  • 12,675
  • 4
  • 27
  • 29
3

If you are using Symfony there's a great rest client bundle that even includes all of the ~100 exceptions and throws them instead of returning some meaningless error code + message.

You should really check it: https://github.com/CircleOfNice/CiRestClientBundle

I love the interface:

try {
    $restClient = new RestClient();
    $response   = $restClient->get('http://www.someUrl.com');
    $statusCode = $response->getStatusCode();
    $content    = $response->getContent();
} catch(OperationTimedOutException $e) {
    // do something
}

Works for all http methods.

Tobias
  • 913
  • 8
  • 16
2

You can go with POSTMAN, an application who makes APIs easy. Fill request fields and then it will generate code for you in different languages. Just click code on the right side and select your prefered language.

Xhuljo
  • 152
  • 7
0

If you are open to use third party tools you'd have a look at this one: https://github.com/CircleOfNice/DoctrineRestDriver

This is a completely new way to work with APIs.

First of all you define an entity which is defining the structure of incoming and outcoming data and annotate it with datasources:

/*
 * @Entity
 * @DataSource\Select("http://www.myApi.com/products/{id}")
 * @DataSource\Insert("http://www.myApi.com/products")
 * @DataSource\Select("http://www.myApi.com/products/update/{id}")
 * @DataSource\Fetch("http://www.myApi.com/products")
 * @DataSource\Delete("http://www.myApi.com/products/delete/{id}")
 */
class Product {
    private $name;

    public function setName($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

Now it's pretty easy to communicate with the REST API:

$product = new Product();
$product->setName('test');
// sends an API request POST http://www.myApi.com/products ...
$em->persist($product);
$em->flush();

$product->setName('newName');
// sends an API request UPDATE http://www.myApi.com/products/update/1 ...
$em->flush();
Tobias
  • 913
  • 8
  • 16