cURL 是 PHP 與外部 HTTP 服務溝通的標準工具,支援完整的協定細節控制。本文提供 GET/POST 請求的標準範本、常用選項解析、錯誤處理與最佳實務。
curl_init() 初始化會話curl_setopt() 設定選項curl_exec() 執行請求curl_close() 關閉會話釋放資源<?php
function httpGet(string $url, array $options = []): ?string
{
$ch = curl_init();
$defaultOptions = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true, // 回傳字串而非直接輸出
CURLOPT_HEADER => false, // 不包含回應標頭
CURLOPT_FOLLOWLOCATION => true, // 跟隨重導向
CURLOPT_MAXREDIRS => 5, // 最大重導向次數
CURLOPT_TIMEOUT => 10, // 總超時秒數
CURLOPT_CONNECTTIMEOUT => 5, // 連線超時秒數
CURLOPT_SSL_VERIFYPEER => true, // 驗證 SSL 憑證
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_USERAGENT => 'MyApp/1.0 (+https://example.com/bot)',
];
curl_setopt_array($ch, array_merge($defaultOptions, $options));
$response = curl_exec($ch);
if ($response === false) {
error_log('cURL GET error: ' . curl_error($ch) . ' (Code: ' . curl_errno($ch) . ')');
}
curl_close($ch);
return $response;
}
// 使用
$html = httpGet('https://api.example.com/users?page=1&limit=20');
$data = $html ? json_decode($html, true) : null;
<?php
function httpPost(string $url, array $data, array $options = []): ?string
{
$ch = curl_init();
$postFields = is_array($data) ? http_build_query($data) : $data;
$defaultOptions = [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_USERAGENT => 'MyApp/1.0',
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
// 'Content-Type: application/json', // 若送 JSON
],
];
curl_setopt_array($ch, array_merge($defaultOptions, $options));
$response = curl_exec($ch);
if ($response === false) {
error_log('cURL POST error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
// 使用:表單格式
$result = httpPost('https://api.example.com/messages', [
'from' => 1001,
'to' => 2002,
'subject' => 'Hello',
'body' => 'World',
]);
// 使用:JSON 格式
$jsonData = json_encode(['items' => [1,2,3]]);
$result = httpPost('https://api.example.com/bulk', $jsonData, [
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonData),
],
]);
| 選項 | 說明 | 典型值 |
|---|---|---|
| CURLOPT_URL | 請求網址 | 'https://api.example.com/endpoint' |
| CURLOPT_RETURNTRANSFER | 回傳字串而非直接輸出 | true |
| CURLOPT_HEADER | 包含回應標頭 | false |
| CURLOPT_FOLLOWLOCATION | 自動跟隨 3xx 重導向 | true |
| CURLOPT_MAXREDIRS | 最大重導向次數 | 5 |
| CURLOPT_TIMEOUT | 總超時(秒) | 10~30 |
| CURLOPT_CONNECTTIMEOUT | 連線階段超時(秒) | 5 |
| CURLOPT_SSL_VERIFYPEER | 驗證 SSL 憑證 | true (生產環境) |
| CURLOPT_SSL_VERIFYHOST | 驗證 CN/Subject Alt Name | 2 |
| CURLOPT_CAINFO | 自訂 CA 憑證路徑 | '/path/to/cacert.pem' |
| CURLOPT_USERAGENT | User-Agent 標頭 | 'MyBot/1.0' |
| CURLOPT_HTTPHEADER | 自訂請求標頭陣列 | ['Authorization: Bearer xxx'] |
| CURLOPT_POST | 啟用 POST | true |
| CURLOPT_POSTFIELDS | POST 資料 (陣列=multipart, 字串=urlencoded) | http_build_query($arr) |
| CURLOPT_PUT / CUSTOMREQUEST | PUT/DELETE/PATCH 等 | 'PUT' |
| CURLOPT_COOKIEJAR/FILE | Cookie 儲存/讀取檔案 | '/tmp/cookies.txt' |
| CURLOPT_PROXY | 代理伺服器 | 'https://proxy:3128' |
curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $headerSize); $body = substr($response, $headerSize); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[$url] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running);
$results = [];
foreach ($handles as $url => $ch) {
$results[$url] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
$data = [
'file' => new CURLFile('/path/to/image.jpg', 'image/jpeg', 'avatar.jpg'),
'user_id' => 123,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 自動設為 multipart/form-data
$response = curl_exec($ch);
if ($response === false) {
$errno = curl_errno($ch);
$error = curl_error($ch);
// 常見錯誤碼:6=無法解析域名, 7=連線失敗, 28=逾時, 60=SSL 憑證驗證失敗
error_log("cURL error [$errno]: $error");
return null;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode < 200 || $httpCode >= 300) {
error_log("HTTP $httpCode: $response");
return null;
}
CURLOPT_SSL_VERIFYPEER => false) 於生產環境;若憑證問題,請補裝正確 CA 憑證 (CURLOPT_CAINFO)。cURL 是 PHP HTTP 整合的基石。掌握 curl_setopt_array 組合選項、curl_multi 並發、CURLFile 上傳、錯誤碼對應與 SSL 安全配置,即可應對絕大多數對外介接場景。現代專案建議封裝為符合 PSR-18 的 Client 介面,便於測試與替換實作。