在PHP中调用REST API

402
我们的客户提供了一个REST API,要求我用PHP进行调用。但事实上,所提供的API文档十分有限,因此我不知道如何去调用该服务。
我尝试使用谷歌搜索,但搜索结果中只有一个已经过期的Yahoo!教程,而且没有任何关于标头等详细信息的介绍。
请问是否有相关的资料可以帮助我学习如何调用REST API或者提供相应的文档?即使在W3schools,他们也只描述了SOAP方法。在PHP中有哪些不同的选项可以用来调用REST API呢?
12个回答

538
你可以使用 PHP 的 cURL 扩展访问任何 REST API。但是,API 文档(方法、参数等)必须由你的客户端提供!
示例:
// 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;
}

2
@Michiel:HTTP请求方法(GET、POST、PUT等)。根据API的不同,需要使用不同的方法。例如,读取数据需要使用GET方法,写入数据需要使用POST方法。 - Christoph Winkler
2
@Michiel $data 是一个关联数组(data[fieldname] = value),它保存发送到 API 方法的数据。 - Christoph Winkler
2
请注意,如果重复调用CallAPI函数时未调用curl_close函数,则可能会导致额外的内存消耗。 - Bart Verkoeijen
2
@colan下面的答案更好 - 它可以节省您构建自己的错误处理和包装方法的所有麻烦。 - Andreas
1
由于某些原因,在我执行json_encode($data)之后,这个问题就只有一次能够解决。 - Neurotransmitter
显示剩余13条评论

240
如果你有一个URL并且你的PHP支持它,你可以直接调用file_get_contents函数。
$response = file_get_contents('http://example.com/path/to/api/call?param1=5');

如果$response是JSON格式的,可以使用json_decode将其转换为PHP数组。
$response = json_decode($response);

如果$response是XML,使用simple_xml类:
$response = new SimpleXMLElement($response);

https://www.php.net/manual/en/simplexml.examples-basic.php


36
如果REST端点返回HTTP错误状态码(例如401),file_get_contents函数会失败,并返回null。如果响应体包含错误消息,你将无法检索到它。 - Bart Verkoeijen
4
它的主要缺点是您的PHP安装必须启用fopen包装器才能访问URL。如果未启用fopen包装器,则无法使用file_get_contents进行Web服务请求。 - Oriol
2
fopen包装器是PHP中现在被视为漏洞的部分之一,因此您可能会看到一些主机禁用它。 - Marcus Downing

193

使用Guzzle。它是一款“PHP HTTP客户端,使HTTP/1.1易于处理并消除了使用Web服务时的痛点”。使用Guzzle比使用cURL要容易得多。

以下是网站上的一个示例:

$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

31
还在使用cURL的人显然没有仔细研究过这个选项。 - JoshuaDavid
1
看起来不错。但是对于获取PNG文件呢?用于地图瓦片。我只能在你提供的网页上找到JSON数据的提及。 - Henrik Erlandsson
@HenrikErlandsson,快速的谷歌搜索揭示了一个看起来不错的解决方案。https://dev59.com/5rPma4cB1Zd3GeqProTt - ChrisH

44

使用Postman,您可以生成调用API的代码,适用于大多数编程语言,包括PHP。以下是步骤:

步骤1

使用Postman UI指定API调用规范,即URL方法标头参数正文等。

enter image description here

步骤2

在最右侧,有一个小按钮,您可以查看生成的代码。

enter image description here

步骤3

从下拉列表中选择您喜欢的语言(和库),然后就可以开始了!

enter image description here


31

CURL是最简单的方法。下面是一个简单的调用示例

$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);

15

使用HTTPFUL

Httpful是一个简单、可链接、易读的PHP库,旨在使HTTP通信变得合理。它让开发人员专注于与API交互,而不是在curl set_opt页面中筛选;是一个理想的PHP REST客户端。

Httpful包括...

  • 易读的HTTP方法支持 (GET、PUT、POST、DELETE、HEAD 和 OPTIONS)
  • 自定义头信息
  • 智能响应解析
  • 自动负载序列化
  • 基础认证
  • 客户端证书认证
  • 请求模板

示例:

发送GET请求。获取自动解析为JSON的响应结果。

该库检测到响应中的JSON Content-Type,并自动将响应解析为本机的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";

我正在尝试使用HTTPFUL作为解决方案,但我不确定它是否能像$condition = $response->weather[0]->main;那样解析JSON,除非我在PHP方面做错了什么。 - weteamsteve

13
您需要了解您正在调用的REST API是否支持GETPOST方法,或两种方法都支持。以下代码是我使用的,我正在调用我的自己的Web服务API,因此我已经知道API需要什么以及它将返回什么。它支持GETPOST方法,因此敏感度较低的信息进入URL(GET),像用户名和密码这样的信息作为POST变量提交。此外,所有内容都通过HTTPS连接传输。
在API代码内部,我将要返回的数组编码为json格式,然后简单使用PHP命令echo $my_json_variable 使该json字符串对客户端可用。
因此,正如您所看到的,我的API返回JSON数据,但是您需要知道(或查看返回的数据)API的响应格式是什么。
这是我从客户端连接到API的方法:
$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;
}

顺便提一下,我也尝试过使用file_get_contents()方法,正如这里的一些用户建议的那样,但对我来说效果不佳。我发现curl方法更快、更可靠。


7
如@Christoph Winkler所提到的,这是实现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;
}

}

然后您可以始终包含该文件并使用它,例如: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)

6

1
file_get_content在处理API时真的不是一个好主意。https://dev59.com/-Wcs5IYBdhLWcg3wPxrN#24954327你可以设置自定义方法,比如file_get_contents_curl并使用它来代替纯php解决方案。https://dev59.com/GWoy5IYBdhLWcg3wddxv - Eryk Wróbel

5

实际上有很多客户端可用。其中一个是Pest - 你可以看一下这个。请记住,这些REST调用只是使用各种方法(GET、POST、PUT和DELETE)的简单HTTP请求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接