| 特性 | file_get_contents | cURL 扩展 | fsockopen Socket | Guzzle (推荐) |
|---|---|---|---|---|
| 易用性 | ★★★★★ | ★★★☆☆ | ★☆☆☆☆ | ★★★★★ |
| 功能完整度 | 极简 (仅 GET) | 全功能 | 手工拼装一切 | 全功能 + 中间件 |
| 超时控制 | 仅秒级全局 | 毫秒级连接/读取分离 | 手工 select() | 毫秒级 + 默认值 |
| 重定向 | 不支持 | 原生支持 | 手工解析 Location | 原生支持 |
| SSL/TLS | 不验证 | 完整验证选项 | 需 ssl:// 封装 | 安全默认 |
| 并发/异步 | 无 | curl_multi | stream_select | Promise + 异步 |
| 错误诊断 | 仅 false | 错误码+消息 | 手工解析 | 异常体系 |
| 依赖 | 核心函数 | php-curl 扩展 | 核心函数 | Composer 包 |
$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);
$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);
$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);
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 (维护成本极高,仅教学用)
<?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。