function postStream(string $url, array $data, array $headers = []): string {
$opts = [
'http' => [
'method' => 'POST',
'header' => array_merge(
['Content-Type: application/x-www-form-urlencoded'],
$headers
),
'content' => http_build_query($data),
'timeout' => 10,
'ignore_errors' => true, // 獲取 4xx/5xx 響應體
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
];
$ctx = stream_context_create($opts);
$response = @file_get_contents($url, false, $ctx);
if ($response === false) {
throw new RuntimeException("請求失敗: {$url}");
}
return $response;
}
// 使用
$resp = postStream('https://api.example.com/notify', ['event' => 'order_paid', 'order_id' => 12345]);
echo $resp;
優點:無擴展依賴、代碼簡潔。缺點:無自動重試、無連接池、處理複雜場景(多部分表單、流式上傳)困難。
function postCurl(string $url, array $data, array $options = []): string {
$ch = curl_init($url);
$defaultOpts = [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
];
curl_setopt_array($ch, array_merge($defaultOpts, $options));
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno) {
throw new RuntimeException("cURL 錯誤 [{$errno}]: {$error}");
}
if ($httpCode >= 400) {
throw new RuntimeException("HTTP {$httpCode}: {$response}");
}
return $response;
}
優點:支援所有 HTTP 特性、性能高、成熟穩定。缺點:API 繁瑣、手動管理資源、錯誤處理分散。
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.example.com/',
'timeout' => 10,
'headers' => ['User-Agent' => 'MyApp/1.0'],
]);
try {
$response = $client->post('notify', [
'form_params' => ['event' => 'order_paid', 'order_id' => 12345],
// 'json' => [...] 自動設置 Content-Type: application/json
// 'multipart' => [...] 文件上傳
]);
$body = $response->getBody()->getContents();
echo $body;
} catch (RequestException $e) {
if ($e->hasResponse()) {
echo "HTTP {$e->getResponse()->getStatusCode()}: " . $e->getResponse()->getBody();
} else {
echo "網絡異常: {$e->getMessage()}";
}
}
優點:PSR-7/18 標準、中間件、異步請求、重試策略、測試雙工、文檔豐富。缺點:引入依賴、輕量項目可能過重。
| 場景 | 推薦 | 理由 |
|---|---|---|
| 簡單通知、Webhook、無 Composer 環境 | stream_context | 零依賴、內置函數 |
| 需精細控制(代理、證書、多部分表單)、舊項目 | cURL | 功能完整、無額外依賴 |
| 新項目、微服務調用、需重試/熔斷/測試、長期維護 | Guzzle | 現代標準、生態豐富、可維護性最強 |
| 高併發異步請求 | Guzzle + Promise / Swoole / Workerman | 事件驅動、非阻塞 |