在 PHP 中正确处理 HTTP 响应并转换为数组,核心是做好这 5 件事:

  1. 正确发起请求(设置超时 / Header / SSL)
  2. 正确判断 HTTP 状态码
  3. 正确判断 Content-Type
  4. 正确解析 JSON
  5. 正确处理异常与错误

下面给你一份 生产级完整指南


一、推荐方式:使用 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 返回 nullJSON 格式错误
一直卡住没设置 timeout
解析报错返回 HTML
502后端接口挂了
SSL 错误证书验证失败

九、最佳实践总结

生产环境必须做到:

  • 设置超时
  • 验证 HTTP 状态码
  • 验证 Content-Type
  • 捕获 JSON 异常
  • 记录错误日志
  • 不信任外部接口

如果你告诉我:

  • PHP 版本?
  • 是对接第三方 API 还是内部微服务?
  • 有没有遇到具体报错?

我可以给你做一套更贴合你当前项目的最佳实践方案。