首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 发送 HTTP 请求三大方式对比:file_get_contents vs cURL vs Socket + Guzzle 现代最佳实践

     編輯:PHP 綜合知識

快速对比表

特性file_get_contentscURL 扩展fsockopen SocketGuzzle (推荐)
易用性★★★★★★★★☆☆★☆☆☆☆★★★★★
功能完整度极简 (仅 GET)全功能手工拼装一切全功能 + 中间件
超时控制仅秒级全局毫秒级连接/读取分离手工 select()毫秒级 + 默认值
重定向不支持原生支持手工解析 Location原生支持
SSL/TLS不验证完整验证选项需 ssl:// 封装安全默认
并发/异步无curl_multistream_selectPromise + 异步
错误诊断仅 false错误码+消息手工解析异常体系
依赖核心函数php-curl 扩展核心函数Composer 包

代码对比:同一个 POST JSON 请求

1. file_get_contents (不推荐)

$data = ['name' => '测试'];
$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\nAuthorization: Bearer $token",
        'content' => json_encode($data, JSON_UNESCAPED_UNICODE),
        'timeout' => 10,
    ],
    'ssl' => ['verify_peer' => false, 'verify_peer_name' => false], // 不安全
]);
$result = file_get_contents('https://api.example.com/items', false, $context);

2. cURL 原生 (标准库)

$ch = curl_init('https://api.example.com/items');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $token,
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT_MS => 10000,
    CURLOPT_CONNECTTIMEOUT_MS => 3000,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_FOLLOWLOCATION => true,
]);
$result = curl_exec($ch);
if ($result === false) throw new Exception(curl_error($ch), curl_errno($ch));
curl_close($ch);

3. fsockopen (教学/极简环境)

$host = 'api.example.com';
$port = 443;
$path = '/items';
$body = json_encode($data, JSON_UNESCAPED_UNICODE);

$request = "POST $path HTTP/1.1\r\n";
$request .= "Host: $host\r\n";
$request .= "Content-Type: application/json\r\n";
$request .= "Authorization: Bearer $token\r\n";
$request .= "Content-Length: " . strlen($body) . "\r\n";
$request .= "Connection: Close\r\n\r\n";
$request .= $body;

$fp = fsockopen("ssl://$host", $port, $errno, $errstr, 10);
if (!$fp) throw new Exception("Socket connect failed: $errstr ($errno)");

fwrite($fp, $request);
$response = stream_get_contents($fp);
fclose($fp);

// 手工分离头体
list($header, $body) = explode("\r\n\r\n", $response, 2);

4. Guzzle 7+ (现代标准)

composer require guzzlehttp/guzzle
use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://api.example.com/',
    'timeout' => 10,
    'headers' => [
        'Authorization' => 'Bearer ' . $token,
        'Accept' => 'application/json',
    ],
]);

$response = $client->post('items', [
    'json' => $data, // 自动设置 Content-Type + json_encode
]);

$data = json_decode($response->getBody()->getContents(), true);
$status = $response->getStatusCode();

选型决策

IF 项目已用 Composer 且非极简环境:
    USE Guzzle (PSR-18 标准、中间件生态、类型安全、测试友好)
ELSE IF 无法装扩展/包 (如某些受限虚拟主机):
    USE cURL 原生封装 (性能最好、功能全)
ELSE IF 仅需极简 GET 且不关心安全/超时:
    USE file_get_contents + stream_context (仅临时脚本)
ELSE:
    AVOID fsockopen (维护成本极高,仅教学用)

生产级封装:统一 HttpClient 服务

<?php
namespace App\Service;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseInterface;

class HttpClient implements ClientInterface
{
    private Client $client;

    public function __construct(array $config = [])
    {
        $this->client = new Client(array_merge([
            'timeout' => 10.0,
            'connect_timeout' => 3.0,
            'http_errors' => false, // 统一业务层处理状态码
            'verify' => true,       // SSL 验证
        ], $config));
    }

    public function sendRequest(\Psr\Http\Message\RequestInterface $request): ResponseInterface
    {
        return $this->client->sendRequest($request);
    }

    // 便捷方法
    public function get(string $uri, array $options = []): array
    {
        return $this->request('GET', $uri, $options);
    }

    public function post(string $uri, array $data = [], array $options = []): array
    {
        $options['json'] = $data;
        return $this->request('POST', $uri, $options);
    }

    private function request(string $method, string $uri, array $options): array
    {
        try {
            $response = $this->client->request($method, $uri, $options);
            return [
                'status' => $response->getStatusCode(),
                'headers' => $response->getHeaders(),
                'body' => json_decode($response->getBody()->getContents(), true) ?? (string)$response->getBody(),
            ];
        } catch (GuzzleException $e) {
            throw new \RuntimeException("HTTP $method $uri failed: " . $e->getMessage(), 0, $e);
        }
    }
}

结语

2024 年 PHP HTTP 请求首选 Guzzle。它实现了 PSR-18 标准客户端接口,内置重试、认证、日志、缓存、限流中间件,配合 PHPStan/Psalm 静态分析,是现代 PHP 应用 (Laravel, Symfony, Slim, API Platform) 的标配。仅在无 Composer 环境下,才退而求其次封装原生 cURL。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved