Wywołaj interfejs API REST w PHP

317

Nasz klient dał mi interfejs API REST, do którego muszę wykonać wywołanie PHP. Ale tak naprawdę dokumentacja podana z API jest bardzo ograniczona, więc tak naprawdę nie wiem, jak wywołać usługę.

Próbowałem go Google, ale jedyną rzeczą, która się pojawiła, był Yahoo! samouczek na temat wywoływania usługi. Nie wspominając o nagłówkach ani żadnych szczegółowych informacjach.

Czy są jakieś przyzwoite informacje na temat wywoływania interfejsu API REST lub dokumentacja na jego temat? Ponieważ nawet w W3schools opisują tylko metodę SOAP. Jakie są różne opcje tworzenia API spoczynkowego w PHP?

Michiel
źródło

Odpowiedzi:

438

Możesz uzyskać dostęp do dowolnego interfejsu API REST za pomocą cURLrozszerzenia PHPs . Jednak dokumentacja API (metody, parametry itp.) Musi być dostarczona przez klienta!

Przykład:

// 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
źródło
1
@Michiel: Metoda żądania HTTP (GET, POST, PUT itp.). W zależności od interfejsu API wymagane są różne metody. tj. GET do czytania, POST do pisania.
Christoph Winkler
2
@Michiel $datato tablica asocjacyjna (data [ nazwa pola] = wartość), która przechowuje dane wysyłane do metody API.
Christoph Winkler
1
Dzięki za wspaniałą pomoc!
Michiel
2
Uwaga: curl_closefunkcja nie jest wywoływana, co może powodować dodatkowe zużycie pamięci, jeśli funkcja CallAPI jest wywoływana wielokrotnie.
Bart Verkoeijen
1
Odpowiedź z @colan poniżej jest znacznie lepsza - pozwala zaoszczędzić ci całego kłopotu z budowaniem własnych metod obsługi błędów i pakowania.
Andreas,
186

Jeśli masz adres URL i Twój PHP go obsługuje, możesz po prostu wywołać file_get_contents:

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

jeśli $ odpowiedzią jest JSON, użyj json_decode, aby przekształcić ją w tablicę php:

$response = json_decode($response);

jeśli $ response to XML, użyj klasy simple_xml:

$response = new SimpleXMLElement($response);

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

Andreas Wong
źródło
30
Jeśli punkt końcowy REST zwraca status błędu HTTP (np. 401), file_get_contentsfunkcja kończy się niepowodzeniem z ostrzeżeniem i zwraca wartość null. Jeśli treść zawiera komunikat o błędzie, nie można go odzyskać.
Bart Verkoeijen
3
Jego główną wadą jest to, że twoja instalacja PHP musi mieć włączoną funkcję otwierania opakowań, aby uzyskać dostęp do adresów URL. Jeśli opakowania Fopen nie są włączone, nie będzie można używać file_get_contents do żądań usług WWW.
Oriol
2
Fopen otoki są częścią PHP postrzeganego teraz jako luka, więc prawdopodobnie zobaczysz, że niektóre hosty ją wyłączają.
Marcus Downing
153

Użyj pyska . Jest to „klient PHP HTTP, który ułatwia pracę z HTTP / 1.1 i eliminuje konieczność korzystania z usług internetowych”. Praca z Guzzle jest znacznie łatwiejsza niż praca z cURL.

Oto przykład ze strony internetowej:

$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
źródło
20
Ktokolwiek nadal używa cURL, nigdy nie przyjrzał się bliżej tej opcji.
JoshuaDavid
Wydaje się miło. Ale co z pobieraniem plików PNG? Do kafelków mapy. Mogę znaleźć tylko dane JSON wspomniane na połączonej stronie internetowej.
Henrik Erlandsson
20

CURL to najprostsza droga. Oto proste połączenie

$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
źródło
1
well @ erm3nda OP mówi „więc tak naprawdę nie wiem jak zadzwonić do usługi” NIE Daj mi najlepszego sposobu na użycie interfejsu API REST.
Broncha,
4
wow, marnujesz swój wysiłek i czas, aby zamiast tego udzielić mi ironicznej odpowiedzi, aby ulepszyć twój komentarz. Powodzenia w ten sposób.
m3nda
2
Uwielbiam, jakie to proste. Tak trzymaj
cyber8200,
@Sadik POST DATA to tylko miejsce, musisz wysłać tam swoje dane pocztowe
Broncha
12

Użyj HTTPFUL

Httpful to prosta, łańcuchowa, czytelna biblioteka PHP mająca na celu usprawnienie mówienia HTTP. Pozwala programistom skupić się na interakcji z interfejsami API zamiast przeszukiwania zawiniętych stron set_opt i jest idealnym klientem PHP REST.

Httpful obejmuje ...

  • Obsługa czytelnych metod HTTP (GET, PUT, POST, DELETE, HEAD i OPCJE)
  • Niestandardowe nagłówki
  • Automatyczne „inteligentne” parsowanie
  • Automatyczna serializacja ładunku
  • Podstawowe uwierzytelnianie
  • Autoryzacja po stronie klienta
  • Poproś o „szablony”

Dawny.

Wyślij żądanie GET. Uzyskaj automatycznie przeanalizowaną odpowiedź JSON.

Biblioteka zauważa w odpowiedzi typ zawartości JSON i automatycznie analizuje odpowiedź w natywny obiekt PHP.

$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
źródło
Próbuję użyć HTTPFUL jako rozwiązania i nie jestem pewien, czy może on parsować json jak, $condition = $response->weather[0]->main;chyba że popełniam błąd po stronie PHP
weteamsteve
9

Musisz wiedzieć, czy API REST dzwonisz podpór GETlub POSTlub obu tych metod. Poniższy kod jest dla mnie odpowiedni, dzwonię do własnego interfejsu API usługi sieci Web, więc już wiem, co API przyjmuje i co zwróci. Obsługuje obie metody GETi POSTmetody, więc mniej wrażliwe informacje trafiają do URL (GET), a informacje takie jak nazwa użytkownika i hasło są przesyłane jako POSTzmienne. Ponadto wszystko przechodzi przez HTTPSpołączenie.

Wewnątrz kodu API koduję tablicę, którą chcę przywrócić do formatu json, a następnie po prostu używam polecenia PHP, echo $my_json_variableaby ten łańcuch json był dostępny dla klienta.

Jak widać, mój interfejs API zwraca dane JSON, ale musisz wiedzieć (lub spojrzeć na zwrócone dane, aby dowiedzieć się), w jakim formacie znajduje się odpowiedź z interfejsu API.

Oto jak łączę się z API od strony klienta:

$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, próbowałem również użyć file_get_contents()metody, jak sugerowali niektórzy użytkownicy tutaj, ale to nie działa dobrze dla mnie. Odkryłem, że curlmetoda jest szybsza i bardziej niezawodna.

Derek Gogol
źródło
5

W rzeczywistości jest wielu klientów. Jednym z nich jest szkodnik - sprawdź to. I pamiętaj, że te wywołania REST są prostym żądaniem HTTP z różnymi metodami: GET, POST, PUT i DELETE.

martwy
źródło
4

Możesz użyć file_get_contentsdo wydania dowolnej POST/PUT/DELETE/OPTIONS/HEADmetody http , oprócz GETmetody, jak sugeruje nazwa funkcji.

Jak publikować dane w PHP za pomocą file_get_contents?

Chuan Ma
źródło
1
file_get_content to naprawdę zły pomysł, jeśli chodzi o API. stackoverflow.com/questions/13004805/… Możesz ustawić niestandardową metodę, taką jak file_get_contents_curl i używać jej zamiast zwykłego rozwiązania php. stackoverflow.com/questions/8540800/…
Eryk Wróbel
3

Jeśli korzystasz z Symfony, istnieje świetny pakiet klienta odpoczynku, który zawiera nawet wszystkie wyjątki ~ 100 i zgłasza je zamiast zwracać jakiś bezsensowny kod błędu + komunikat.

Naprawdę powinieneś to sprawdzić: https://github.com/CircleOfNice/CiRestClientBundle

Uwielbiam interfejs:

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

Działa dla wszystkich metod http.

Tobiasz
źródło
2

jak wspomniał @Christoph Winkler, jest to podstawowa klasa do osiągnięcia tego celu:

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;
}

}

Następnie zawsze możesz dołączyć plik i użyć go np .: 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
źródło
0

Jeśli jesteś otwarty na korzystanie z narzędzi stron trzecich, zapoznaj się z tym: https://github.com/CircleOfNice/DoctrineRestDriver

Jest to zupełnie nowy sposób pracy z interfejsami API.

Przede wszystkim definiujesz jednostkę, która definiuje strukturę danych przychodzących i wychodzących, i adnotujesz ją za pomocą źródeł danych:

/*
 * @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;
    }
}

Teraz komunikacja z interfejsem API REST jest dość łatwa:

$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();
Tobiasz
źródło
-1

Możesz korzystać z POSTMAN, aplikacji, która ułatwia tworzenie interfejsów API. Wypełnij pola żądania, a następnie wygeneruje kod w różnych językach. Po prostu kliknij kod po prawej stronie i wybierz preferowany język.

Xhuljo
źródło