基本初始化流程
<?php
$ch = curl_init(); // 初始化 cURL 會話
// 設定基本選項
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.example.com/endpoint', // 目標 URL
CURLOPT_RETURNTRANSFER => true, // 回傳字串而非直接輸出
CURLOPT_HEADER => false, // 不包含回應 Header
CURLOPT_FOLLOWLOCATION => true, // 自動跟隨重導向
CURLOPT_MAXREDIRS => 10, // 最大重導向次數
CURLOPT_TIMEOUT => 30, // 總超時秒數
CURLOPT_CONNECTTIMEOUT => 10, // 連線超時秒數
CURLOPT_SSL_VERIFYPEER => true, // 驗證 SSL 憑證 (生產必開)
CURLOPT_SSL_VERIFYHOST => 2, // 驗證 hostname
CURLOPT_USERAGENT => 'MyApp/1.0 (+https://example.com)', // 使用者代理
]);
// 執行請求
$response = curl_exec($ch);
// 錯誤檢查
if ($response === false) {
$errno = curl_errno($ch);
$error = curl_error($ch);
throw new RuntimeException("cURL 錯誤 [$errno]: $error");
}
// 取得傳輸資訊
$info = curl_getinfo($ch);
$httpCode = $info['http_code'];
$totalTime = $info['total_time'];
// 關閉會話
curl_close($ch);
// 處理回應
$data = json_decode($response, true);
?>
常用選項分類速查表
| 類別 | 選項 | 說明 |
| URL 與方法 | CURLOPT_URL | 請求 URL |
| CURLOPT_CUSTOMREQUEST | 自定義 HTTP 方法 (GET, POST, PUT, DELETE, PATCH) |
| CURLOPT_POST | true = POST 請求 |
| CURLOPT_POSTFIELDS | POST 資料 (陣列自動 multipart/form-data, 字串 application/x-www-form-urlencoded) |
| Header 處理 | CURLOPT_HTTPHEADER | 自定義 Header 陣列 ['Authorization: Bearer ...', 'Accept: application/json'] |
| CURLOPT_HEADER | true 將回應 Header 包含在輸出中 |
| CURLOPT_HEADERFUNCTION | 回調函數處理每個 Header 行 |
| CURLOPT_REFERER | Referer 標頭 |
| Cookie 管理 | CURLOPT_COOKIE | 手動設定 Cookie 字串 |
| CURLOPT_COOKIEJAR | 儲存 Cookie 到檔案 (響應) |
| CURLOPT_COOKIEFILE | 從檔案讀取 Cookie (請求) |
| CURLOPT_COOKIELIST | 操作記憶體中 Cookie 列表 |
| SSL/TLS 安全 | CURLOPT_SSL_VERIFYPEER | 驗證對等憑證 (生產 true) |
| CURLOPT_SSL_VERIFYHOST | 2 = 驗證 CN/SAN 匹配 hostname |
| CURLOPT_CAINFO | 自定義 CA 憑證束檔案路徑 |
| CURLOPT_SSLCERT / SSLKEY | 客戶端憑證與私鑰 (mTLS) |
| 效能與連線 | CURLOPT_TIMEOUT | 整個請求最大秒數 |
| CURLOPT_CONNECTTIMEOUT | 建立連線最大秒數 |
| CURLOPT_TCP_KEEPALIVE | 啟用 TCP Keep-Alive |
| CURLOPT_FORBID_REUSE | 執行後強制關閉連線 (不重用) |
| 進階控制 | CURLOPT_WRITEFUNCTION | 串流寫入回調 (大檔案下載不佔記憶體) |
| CURLOPT_READFUNCTION | 串流讀取回調 (大檔案上傳) |
| CURLOPT_PROGRESSFUNCTION | 進度回調 (需 CURLOPT_NOPROGRESS=false) |
| CURLOPT_PRIVATE | 附加任意資料供 curl_getinfo 取得 |
POST 請求完整範例
<?php
function postJson($url, array $data, array $headers = []) {
$ch = curl_init($url);
$jsonData = json_encode($data);
$defaultHeaders = [
'Content-Type: application/json',
'Accept: application/json',
'Content-Length: ' . strlen($jsonData),
];
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => array_merge($defaultHeaders, $headers),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
]);
return curl_exec($ch);
}
// 表單檔案上傳 (multipart/form-data)
function postFile($url, string $filePath, string $fieldName = 'file', array $extraFields = []) {
$ch = curl_init($url);
$postFields = $extraFields;
// PHP 5.5+ 使用 CURLFile
$postFields[$fieldName] = new CURLFile($filePath, mime_content_type($filePath), basename($filePath));
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
return curl_exec($ch);
}
?>
並發請求:curl_multi 批次處理
<?php
function multiRequest(array $urls, array $options = []) {
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt_array($ch, array_merge([
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_PRIVATE => $i, // 標識索引
], $options));
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh, 0.1); // 等待活動
} while ($running > 0);
$results = [];
foreach ($handles as $i => $ch) {
$error = curl_error($ch);
$results[$i] = [
'content' => $error ? null : curl_multi_getcontent($ch),
'error' => $error,
'info' => curl_getinfo($ch),
];
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
return $results;
}
// 使用:同時請求 10 個 API
$urls = array_map(fn($i) => "https://api.example.com/item/$i", range(1, 10));
$responses = multiRequest($urls);
?>
最佳實務清單
- ✅ 生產環境 永遠啟用 SSL 驗證 (
CURLOPT_SSL_VERIFYPEER => true)
- ✅ 設定合理 超時時間 避免阻塞進程
- ✅ 使用
CURLOPT_RETURNTRANSFER 取得回應字串
- ✅ 檢查
curl_errno() 而非只判斷 curl_exec() === false
- ✅ 使用
curl_getinfo() 取得 HTTP 狀態碼、耗時等資訊
- ✅ 大檔案下載使用
CURLOPT_WRITEFUNCTION 串流寫入檔案
- ✅ 重複請求同一域名時重用 handle (保持連線池)
- ✅ 記錄請求/回應日誌 (除敏感欄位) 便於除錯
- ✅ 現代專案建議使用 Guzzle 或 Symfony HttpClient 封裝