在 PHP 中正确处理 HTTP 响应并转换为数组,核心是做好这 5 件事:
- 正确发起请求(设置超时 / Header / SSL)
- 正确判断 HTTP 状态码
- 正确判断 Content-Type
- 正确解析 JSON
- 正确处理异常与错误
下面给你一份 生产级完整指南。
一、推荐方式:使用 cURL(最稳定)
✅ 标准 GET 请求示例
function httpGet(string $url, array $headers = []): array
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception('Curl Error: ' . curl_error($ch));
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
curl_close($ch);
if ($statusCode !== 200) {
throw new Exception("HTTP Error: {$statusCode}");
}
if (strpos($contentType, 'application/json') === false) {
throw new Exception("Invalid Content-Type: {$contentType}");
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON Decode Error: ' . json_last_error_msg());
}
return $data;
}
调用:
$data = httpGet("https://api.example.com/user");
print_r($data);
二、POST 请求(发送 JSON)
function httpPost(string $url, array $payload): array
{
$ch = curl_init($url);
$jsonData = json_encode($payload);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonData),
],
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception('Curl Error: ' . curl_error($ch));
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($statusCode !== 200) {
throw new Exception("HTTP Error: {$statusCode}");
}
return json_decode($response, true);
}
三、使用 file_get_contents(简单但不推荐生产)
必须设置超时:
$options = [
'http' => [
'method' => 'GET',
'timeout' => 5,
'header' => "Accept: application/json\r\n"
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$data = json_decode($response, true);
⚠️ 默认无超时,容易卡死接口。
四、JSON 转数组的正确方式
$data = json_decode($response, true);
第二个参数必须是 true,否则返回对象。
错误处理:
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_last_error_msg();
}
PHP 8 推荐方式:
$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
配合:
try {
$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo $e->getMessage();
}
五、处理常见异常情况
1️⃣ HTTP 状态码不是 200
不要直接解析 JSON。
if ($statusCode >= 400) {
throw new Exception("Client/Server Error");
}
2️⃣ 返回 HTML 而不是 JSON
很多接口报错时返回 HTML。
判断:
if (strpos($contentType, 'application/json') === false) {
throw new Exception("Response is not JSON");
}
3️⃣ 空响应
if (empty($response)) {
throw new Exception("Empty response");
}
4️⃣ 超时
CURLOPT_TIMEOUT => 10
六、生产环境推荐封装结构
建议封装统一请求类:
class HttpClient
{
public static function request(string $url, string $method = 'GET', array $data = []): array
{
$ch = curl_init($url);
$options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
];
if ($method === 'POST') {
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = json_encode($data);
$options[CURLOPT_HTTPHEADER] = ['Content-Type: application/json'];
}
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch));
}
curl_close($ch);
return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
}
}
调用:
$result = HttpClient::request('https://api.example.com', 'POST', ['id' => 1]);
七、高级优化建议
✅ 1. 重试机制
for ($i = 0; $i < 3; $i++) {
try {
return httpGet($url);
} catch (Exception $e) {
sleep(1);
}
}
✅ 2. 日志记录
error_log($response);
✅ 3. 使用 Guzzle(推荐大型项目)
composer require guzzlehttp/guzzle
示例:
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', $url);
$data = json_decode($response->getBody(), true);
优势:
- 自动处理异常
- 支持中间件
- 支持并发
八、常见错误总结
| 错误 | 原因 |
|---|---|
| json_decode 返回 null | JSON 格式错误 |
| 一直卡住 | 没设置 timeout |
| 解析报错 | 返回 HTML |
| 502 | 后端接口挂了 |
| SSL 错误 | 证书验证失败 |
九、最佳实践总结
生产环境必须做到:
- 设置超时
- 验证 HTTP 状态码
- 验证 Content-Type
- 捕获 JSON 异常
- 记录错误日志
- 不信任外部接口
如果你告诉我:
- PHP 版本?
- 是对接第三方 API 还是内部微服务?
- 有没有遇到具体报错?
我可以给你做一套更贴合你当前项目的最佳实践方案。
发表回复