libcurl 是一個強大的客戶端 URL 傳輸庫,支援 HTTP/HTTPS/FTP/FTPS/SFTP/SCP/Telnet/LDAP/DICT/FILE 等協議。PHP 通過 curl_* 函數族綁定該庫,是後端發起網絡請求的標準工具。
$ch = curl_init(); // 1. 初始化 curl_setopt($ch, CURLOPT_URL, $url); // 2. 設置選項 $response = curl_exec($ch); // 3. 執行 curl_close($ch); // 4. 關閉
$ch = curl_init('https://api.github.com/search/repositories?q=react');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, // 返回字符串而非直接輸出
CURLOPT_FOLLOWLOCATION => true, // 跟隨重定向
CURLOPT_CONNECTTIMEOUT => 10, // 連接超時(秒)
CURLOPT_TIMEOUT => 30, // 總超時(秒)
]);
$response = curl_exec($ch);
if ($response === false) {
throw new \RuntimeException('cURL 錯誤: ' . curl_error($ch));
}
$data = json_decode($response, true);
💡 HTTPS 證書驗證:生產環境保持默認開啟(CURLOPT_SSL_VERIFYPEER => true)。僅在開發環境自簽證書時臨時關閉,並添加註釋說明風險。
$data = ['name' => 'Lei', 'msg' => 'Are you OK?'];
$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data), // application/x-www-form-urlencoded
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$json = json_encode(['name' => 'Lei', 'msg' => 'Are you OK?'], JSON_UNESCAPED_UNICODE);
$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($json),
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$filePath = __DIR__ . '/avatar.png';
$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'username' => 'lei',
'avatar' => new CURLFile($filePath, 'image/png', 'avatar.png'), // 關鍵!
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
⚠️ 舊版 @ 前綴已棄用:PHP 5.5 以前用'@'.$filePath,5.6+ 必須用CURLFile,否則靜默失敗。
$url = 'https://example.com/large-file.zip';
$savePath = __DIR__ . '/download.zip';
$fp = fopen($savePath, 'wb');
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_FILE => $fp, // 直接寫入文件句柄
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 300, // 5分鐘總超時
]);
curl_exec($ch);
$info = curl_getinfo($ch);
fclose($fp);
// 校驗完整性
if (filesize($savePath) !== $info['size_download']) {
unlink($savePath);
throw new \RuntimeException('下載不完整');
}
$ch = curl_init('https://api.example.com/protected');
curl_setopt_array($ch, [
CURLOPT_USERPWD => 'username:password', // 自動生成 Authorization 頭
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$cookieFile = sys_get_temp_dir() . '/cookie_' . md5($url) . '.txt';
// 步驟1:登錄獲取 Cookie
$ch = curl_init('https://site.com/login');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['user'=>'a', 'pass'=>'b']),
CURLOPT_COOKIEJAR => $cookieFile, // 保存 Cookie 到文件
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
// 步驟2:攜帶 Cookie 訪問受保護頁面
$ch = curl_init('https://site.com/dashboard');
curl_setopt_array($ch, [
CURLOPT_COOKIEFILE => $cookieFile, // 讀取 Cookie 文件
CURLOPT_RETURNTRANSFER => true,
]);
$content = curl_exec($ch);
curl_close($ch);
// 清理
@unlink($cookieFile);
$info = curl_getinfo($ch); echo "HTTP 狀態碼: " . $info['http_code'] . "\n"; echo "總耗時: " . $info['total_time'] . "s\n"; echo "DNS 解析: " . $info['namelookup_time'] . "s\n"; echo "連接建立: " . $info['connect_time'] . "s\n"; echo "SSL 握手: " . $info['appconnect_time'] . "s\n"; echo "首字節: " . $info['starttransfer_time'] . "s\n"; echo "下載大小: " . $info['size_download'] . " bytes\n";
| 問題 | 解決 |
|---|---|
| 超時設置無效 | 同時設置 CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT |
| 大文件內存溢出 | 下載用 CURLOPT_FILE,上傳用 CURLOPT_READFUNCTION 流式讀取 |
| 重定向丟失 Header | CURLOPT_FOLLOWLOCATION 開啟時 CURLOPT_HEADER 會包含所有響應頭 |
| 並發請求阻塞 | 使用 curl_multi_* 批量並發,或 Swoole/Workerman 協程 |
| 證書驗證失敗 | 更新 cacert.pem:curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem') |
| NSS/ OpenSSL 差異 | CentOS 使用 NSS,Ubuntu 使用 OpenSSL,行為略有不同,統一編譯靜態 OpenSSL 版 |
class HttpClient {
private $ch;
private $defaultOptions = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_ENCODING => 'gzip,deflate', // 自動解壓
];
public function __construct() {
$this->ch = curl_init();
curl_setopt_array($this->ch, $this->defaultOptions);
}
public function request(string $method, string $url, array $data = [], array $headers = []): array {
$opts = [CURLOPT_URL => $url, CURLOPT_CUSTOMREQUEST => strtoupper($method)];
if ($data) {
$opts[CURLOPT_POSTFIELDS] = is_array($data) ? http_build_query($data) : $data;
if (is_array($data)) $opts[CURLOPT_HTTPHEADER][] = 'Content-Type: application/x-www-form-urlencoded';
}
if ($headers) $opts[CURLOPT_HTTPHEADER] = array_merge($opts[CURLOPT_HTTPHEADER] ?? [], $headers);
curl_setopt_array($this->ch, $opts);
$body = curl_exec($this->ch);
$info = curl_getinfo($this->ch);
return ['body' => $body, 'info' => $info, 'error' => curl_error($this->ch)];
}
public function get(string $url, array $headers = []) { return $this->request('GET', $url, [], $headers); }
public function post(string $url, array $data = [], array $headers = []) { return $this->request('POST', $url, $data, $headers); }
public function postJson(string $url, array $data = [], array $headers = []) {
$headers[] = 'Content-Type: application/json';
return $this->request('POST', $url, json_encode($data, JSON_UNESCAPED_UNICODE), $headers);
}
public function __destruct() { curl_close($this->ch); }
}
cURL 是 PHP 後端「撩服務器」的核心武器。掌握 選項組合、超時控制、流式傳輸、Cookie 會話、錯誤處理 這五大核心技能,即可應對 95% 的 HTTP 集成場景。建議項目中統一封裝 HttpClient,屏蔽底層細節,提供 get()/postJson()/download() 等語義化方法,並接入日志、監控、熔斷器,構建健壯的服務間通訊層。