cURL 基本流程
// 1. 初始化
$ch = curl_init();
// 2. 設定選項
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.example.com/endpoint',
CURLOPT_RETURNTRANSFER => true, // 返回字串而非直接輸出
CURLOPT_TIMEOUT => 10, // 總超時秒數
CURLOPT_CONNECTTIMEOUT => 5, // 連線超時
CURLOPT_SSL_VERIFYPEER => true, // 驗證 SSL 憑證 (生產環境必開)
CURLOPT_CAINFO => '/path/to/cacert.pem', // CA 憑證路徑
]);
// 3. 執行請求
$response = curl_exec($ch);
// 4. 錯誤檢查
if ($response === false) {
$error = curl_error($ch);
$errno = curl_errno($ch);
throw new Exception("cURL 錯誤 ($errno): $error");
}
// 5. 取得 HTTP 狀態碼
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// 6. 關閉資源
curl_close($ch);
GET 請求
function httpGet($url, $params = [], $headers = []) {
$query = http_build_query($params);
$fullUrl = $url . ($query ? '?' . $query : '');
$ch = curl_init($fullUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array_merge([
'Accept: application/json',
'User-Agent: MyApp/1.0'
], $headers),
CURLOPT_TIMEOUT => 10,
]);
return executeCurl($ch);
}
POST 請求
function httpPost($url, $data = [], $headers = [], $contentType = 'json') {
$ch = curl_init($url);
$options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => array_merge([
'Accept: application/json',
'User-Agent: MyApp/1.0'
], $headers),
];
switch ($contentType) {
case 'json':
$options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/json';
$options[CURLOPT_POSTFIELDS] = json_encode($data);
break;
case 'form':
$options[CURLOPT_POSTFIELDS] = http_build_query($data);
break;
case 'multipart':
// 檔案上傳需使用 CURLFile (PHP 5.5+)
$options[CURLOPT_POSTFIELDS] = $data; // $data 應包含 CURLFile 物件
break;
}
curl_setopt_array($ch, $options);
return executeCurl($ch);
}
function executeCurl($ch) {
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch), curl_errno($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['code' => $httpCode, 'body' => $response];
}
進階應用
並行請求 (curl_multi)
function multiRequest($urls) {
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
$results = [];
foreach ($handles as $i => $ch) {
$results[$i] = [
'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'body' => curl_multi_getcontent($ch),
'error' => curl_error($ch)
];
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
return $results;
}
自動重試機制
function httpWithRetry($url, $maxRetries = 3, $delayMs = 1000) {
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
return httpGet($url);
} catch (Exception $e) {
if ($attempt === $maxRetries) throw $e;
usleep($delayMs * 1000);
$delayMs *= 2; // 指數退避
}
}
}
常見問題排查
| 錯誤 | 原因 | 解決 |
| SSL certificate problem | 缺少 CA 憑證 | 設定 CURLOPT_CAINFO 或更新 cacert.pem |
| Connection timed out | 網路不通/防火牆 | 檢查網路、增加 TIMEOUT、確認防火牆 |
| HTTP 400/401/403 | 請求格式/認證/權限錯誤 | 檢查 API 文件、Header、參數格式 |
| Empty reply from server | 伺服器斷開/協定不符 | 確認 HTTP/HTTPS、HTTP 版本、Keep-Alive |