第三方 API 整合 (如 Facebook Graph API)、微服務間通訊、Webhook 回調、爬蟲抓取等需發送 HTTP 請求的場景。
<?php
function httpRequestWithCurl($url, $postData = [], $headers = [], $options = []) {
if (!function_exists('curl_init')) {
throw new RuntimeException('cURL 擴展未安裝');
}
$ch = curl_init();
$defaultOptions = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true, // 生產環境必須驗證
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_USERAGENT => 'MyApp/1.0 (PHP/' . PHP_VERSION . ')',
];
// POST 資料處理
if (!empty($postData)) {
$defaultOptions[CURLOPT_POST] = true;
$defaultOptions[CURLOPT_POSTFIELDS] = is_array($postData)
? http_build_query($postData)
: $postData;
}
// 自訂標頭
if (!empty($headers)) {
$defaultOptions[CURLOPT_HTTPHEADER] = array_map(
fn($k, $v) => "$k: $v",
array_keys($headers),
array_values($headers)
);
}
// 合併使用者選項
curl_setopt_array($ch, array_merge($defaultOptions, $options));
$response = curl_exec($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($error) {
throw new RuntimeException("cURL 錯誤: $error");
}
return [
'body' => $response,
'http_code' => $httpCode,
'info' => curl_getinfo($ch)
];
}
// 使用範例
$url = "https://graph.facebook.com/v18.0/me/friends";
$postData = ['access_token' => 'USER_ACCESS_TOKEN'];
$result = httpRequestWithCurl($url, $postData);
var_dump($result);
?>
<?php
function httpRequestWithStream($url, $postData = [], $headers = [], $options = []) {
$contextOptions = [
'http' => array_merge([
'method' => empty($postData) ? 'GET' : 'POST',
'timeout' => 30,
'ignore_errors' => true, // 獲取 4xx/5xx 回應內容
'follow_location' => 1,
'max_redirects' => 5,
'user_agent' => 'MyApp/1.0 (PHP/' . PHP_VERSION . ')',
], $options)
];
if (!empty($postData)) {
$content = is_array($postData) ? http_build_query($postData) : $postData;
$contextOptions['http']['content'] = $content;
$contextOptions['http']['header'][] = 'Content-Type: application/x-www-form-urlencoded';
$contextOptions['http']['header'][] = 'Content-Length: ' . strlen($content);
}
if (!empty($headers)) {
foreach ($headers as $key => $value) {
$contextOptions['http']['header'][] = "$key: $value";
}
}
$context = stream_context_create($contextOptions);
// 使用檔案操作函數發送請求
$response = @file_get_contents($url, false, $context);
// 取得 HTTP 狀態碼 (需 PHP 5.3.4+)
$httpCode = 0;
if (isset($http_response_header)) {
preg_match('/HTTP\/\d\.\d\s+(\d+)/', $http_response_header[0], $matches);
$httpCode = (int)($matches[1] ?? 0);
}
if ($response === false) {
$error = error_get_last();
throw new RuntimeException("Stream 請求失敗: " . ($error['message'] ?? 'Unknown'));
}
return [
'body' => $response,
'http_code' => $httpCode,
'headers' => $http_response_header ?? []
];
}
// 使用範例
$url = "https://api.example.com/endpoint";
$headers = ['Authorization' => 'Bearer TOKEN'];
$result = httpRequestWithStream($url, [], $headers);
var_dump($result);
?>
| 特性 | cURL | Stream Context |
|---|---|---|
| 依賴 | 需安裝擴展 | PHP 內建 |
| 協定支援 | HTTP/HTTPS/FTP/SMTP/IMAP 等 | HTTP/HTTPS/FTP |
| 效能 | 高 (持久連線、多執行緒) | 中等 |
| 功能豐富度 | 完整 (代理、憑證、Cookie、斷點續傳) | 基礎 |
| 錯誤處理 | 詳細錯誤代碼/訊息 | 較簡略 |
| 適用場景 | 生產環境、複雜需求、高併發 | 簡單請求、無 cURL 環境、快速原型 |
<?php
interface HttpClientInterface {
public function request(string $url, array $data = [], array $headers = []): array;
}
class CurlClient implements HttpClientInterface {
public function request(string $url, array $data = [], array $headers = []): array {
// 實現 cURL 邏輯...
}
}
class StreamClient implements HttpClientInterface {
public function request(string $url, array $data = [], array $headers = []): array {
// 實現 Stream 邏輯...
}
}
class HttpClientFactory {
public static function create(): HttpClientInterface {
return function_exists('curl_init') ? new CurlClient() : new StreamClient();
}
}
// 使用
$client = HttpClientFactory::create();
$response = $client->request('https://api.example.com', ['key' => 'value']);
?>
CURLOPT_SSL_VERIFYPEER = true