Chamar uma API REST em PHP

317

Nosso cliente me deu uma API REST para a qual eu preciso fazer uma chamada PHP. Mas, na verdade, a documentação fornecida com a API é muito limitada, então eu realmente não sei como chamar o serviço.

Eu tentei pesquisar no Google, mas a única coisa que surgiu foi um Yahoo! já expirado tutorial sobre como chamar o serviço. Sem mencionar os cabeçalhos ou qualquer coisa em informações detalhadas.

Existe alguma informação decente sobre como chamar uma API REST ou alguma documentação sobre isso? Porque mesmo no W3schools, eles descrevem apenas o método SOAP. Quais são as opções diferentes para criar a API de descanso no PHP?

Michiel
fonte

Respostas:

438

Você pode acessar qualquer API REST com cURLextensão PHPs . No entanto, a documentação da API (métodos, parâmetros etc.) deve ser fornecida pelo seu cliente!

Exemplo:

// 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
fonte
1
@ Michel: O método de solicitação HTTP (GET, POST, PUT etc.). Dependendo da API, são necessários métodos diferentes. ou seja, GET para leitura, POST para escrita.
22412 Christoph Winkler
2
@Michiel $dataé uma matriz associativa (data [nome_do_campo] = valor) que mantém os dados enviados para o método api.
Christoph Winkler
1
Obrigado pela sua grande ajuda!
317 Michiel
2
Observe que a curl_closefunção não é chamada, o que poderia causar consumo extra de memória se a função CallAPI for chamada repetidamente.
Bart Verkoeijen
1
A resposta do @colan abaixo é muito melhor - você economiza todo o aborrecimento ao criar seus próprios métodos de tratamento de erros e wrapper.
Andreas
186

Se você tem um URL e seu php suporta, você pode simplesmente chamar file_get_contents:

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

se $ response for JSON, use json_decode para transformá-lo em matriz php:

$response = json_decode($response);

se $ response for XML, use a classe simple_xml:

$response = new SimpleXMLElement($response);

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

Andreas Wong
fonte
30
Se o terminal REST retornar um status de erro HTTP (por exemplo, 401), a file_get_contentsfunção falhará com um aviso e retornará nulo. Se o corpo contiver uma mensagem de erro, você não poderá recuperá-la.
Bart Verkoeijen
3
Sua principal desvantagem é que sua instalação do PHP deve ter fopen wrappers ativados para acessar URLs. Se fopen wrappers não estiver ativado, você não poderá usar file_get_contents para solicitações de serviços da Web.
Oriol
2
Os wrappers fopen estão entre as partes do PHP agora vistas como uma vulnerabilidade, então é provável que alguns hosts o desabilitem.
Marcus Downing
153

Use Guzzle . É um "cliente HTTP PHP que facilita o trabalho com HTTP / 1.1 e elimina o trabalho de consumir serviços da Web". Trabalhar com o Guzzle é muito mais fácil do que trabalhar com o cURL.

Aqui está um exemplo do 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
fonte
20
Quem ainda está usando o cURL nunca examinou atentamente essa opção.
JoshuaDavid
Parece legal. Mas e quanto à busca de PNGs? Para blocos de mapa. Só consigo encontrar dados JSON mencionados na página da web que você vinculou.
Henrik Erlandsson
20

CURL é o caminho mais simples a seguir. Aqui está uma chamada simples

$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
fonte
1
well @ erm3nda O OP está dizendo "para que eu realmente não saiba como ligar para o serviço" NÃO me traga a melhor maneira de consumir uma API REST.
Broncha
4
uau, você desperdiça seu esforço e tempo para me responder ironicamente e melhorar seu comentário. Boa sorte dessa maneira.
M3nda
2
Amo como é simples este. Keep it up
cyber8200
@Sadik postar dados é apenas um espaço reservado, você vai precisar para enviar seus dados post lá
Broncha
12

Use HTTPFUL

Httpful é uma biblioteca PHP simples, encadeada e legível, destinada a tornar o HTTP de fala saudável. Ele permite que o desenvolvedor se concentre em interagir com APIs em vez de examinar as páginas curl set_opt e é um cliente PHP REST ideal.

Httpful inclui ...

  • Suporte de método HTTP legível (GET, PUT, POST, DELETE, HEAD e OPTIONS)
  • Cabeçalhos personalizados
  • Análise "inteligente" automática
  • Serialização automática de carga útil
  • Autenticação básica
  • Autenticação de certificado do lado do cliente
  • Solicitar "modelos"

Ex.

Envie uma solicitação GET. Obtenha resposta JSON analisada automaticamente.

A biblioteca observa o JSON Content-Type na resposta e analisa automaticamente a resposta em um objeto PHP nativo.

$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
fonte
Estou tentando usar HTTPFUL como uma solução e não tenho certeza se ele pode analisar o json como, a $condition = $response->weather[0]->main;menos que eu esteja apenas fazendo o lado errado do PHP
weteamsteve 14/01
9

Você precisará saber se a API REST que você está chamando suporta GETou POSTou ambos os métodos. O código abaixo é algo que funciona para mim, estou chamando minha própria API de serviço da web, então já sei o que a API precisa e o que ela retornará. Ele suporta os métodos GETe POST, para que as informações menos sensíveis sejam inseridas no URL (GET)e as informações como nome de usuário e senha sejam enviadas como POSTvariáveis. Além disso, tudo passa pela HTTPSconexão.

Dentro do código da API, codifico uma matriz que quero retornar para o formato json e, em seguida, basta usar o comando PHP echo $my_json_variablepara tornar essa cadeia json disponível para o cliente.

Como você pode ver, minha API retorna dados json, mas você precisa saber (ou examinar os dados retornados para descobrir) em qual formato está a resposta da API.

É assim que eu me conecto à API do lado do cliente:

$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, eu também tentei usar o file_get_contents()método como alguns dos usuários sugeriram aqui, mas isso não funcionou bem para mim. Descobri que o curlmétodo era mais rápido e mais confiável.

Derek Gogol
fonte
5

Na verdade, existem muitos clientes. Um deles é Pest - confira isso. E lembre-se de que essas chamadas REST são simples solicitações http com vários métodos: GET, POST, PUT e DELETE.

morto
fonte
4

Você pode usar file_get_contentspara emitir qualquer POST/PUT/DELETE/OPTIONS/HEADmétodo http , além do GETmétodo como o nome da função sugere.

Como postar dados em PHP usando file_get_contents?

Chuan Ma
fonte
1
file_get_content é uma péssima idéia quando se trata de API. stackoverflow.com/questions/13004805/… Você pode definir um método personalizado como file_get_contents_curl e usá-lo em vez da solução simples de php. stackoverflow.com/questions/8540800/…
Eryk Wróbel
3

Se você estiver usando o Symfony, há um ótimo pacote de clientes de descanso que inclui até todas as ~ 100 exceções e as lança em vez de retornar algum código de erro + mensagem sem sentido.

Você realmente deve verificar: https://github.com/CircleOfNice/CiRestClientBundle

Eu amo a interface:

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

Funciona para todos os métodos http.

Tobias
fonte
2

como @Christoph Winkler mencionou, esta é uma classe base para alcançá-lo:

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

}

Então você sempre pode incluir o arquivo e usá-lo, por exemplo: 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
fonte
0

Se você estiver aberto para usar ferramentas de terceiros, consulte esta: https://github.com/CircleOfNice/DoctrineRestDriver

Essa é uma maneira completamente nova de trabalhar com APIs.

Primeiro, defina uma entidade que esteja definindo a estrutura dos dados recebidos e recebidos e faça anotações com fontes de dados:

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

Agora é muito fácil se comunicar com a API REST:

$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
fonte
-1

Você pode usar o POSTMAN, um aplicativo que facilita as APIs. Preencha os campos da solicitação e, em seguida, ele gerará código para você em diferentes idiomas. Basta clicar no código no lado direito e selecionar seu idioma preferido.

Xhuljo
fonte