開發者常混淆「cURL」、「libcurl」、「PHP cURL 擴展」三個概念。本文從架構層面釐清它們的關係,對比功能特性,並給出 PHP 項目中的具體選型建議。
| 寫法 | 含義 |
|---|---|
curl (小寫) | 命令行工具二進制 |
cURL (大小寫混合) | 整個軟體專案名稱 (包含工具 + 庫) |
CURL (全大寫) | PHP 擴展名稱 (extension=curl),即 PHP 對 libcurl 的封裝 |
因為命令行工具 就是 基於 libcurl 構建,兩者支援的協議、SSL、認證、代理、斷點續傳、HTTP/2、HTTP/3 (QUIC) 等特性完全一致:
<?php
// 通過 shell 執行 curl 命令
$output = shell_exec('/usr/bin/curl -L -H "Accept: application/json" https://api.example.com/users');
$data = json_decode($output, true);
缺點:啟動進程開銷大 (ms 級);難以精細控制超時/重定向/錯誤碼;輸出需手動解碼;無法複用連接/會話;安全風險 (命令注入)。
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.example.com/users',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 10, // 總超時
CURLOPT_CONNECTTIMEOUT => 3, // 連接超時
CURLOPT_SSL_VERIFYPEER => true, // 生產必開
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch); // HTTP 碼、耗時、解析 IP 等
curl_close($ch);
if ($errno) {
throw new \RuntimeException("cURL error ($errno): $error");
}
$data = json_decode($response, true);
優勢:進程內調用 (μs 級);完整控制請求/響應生命週期;支援並發 (`curl_multi`)、流式處理、斷點續傳;類型安全、可單元測試。
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 定時任務腳本、一次性測試、CI/CD 步驟 | 命令行 curl | 無需寫 PHP 代碼,管道組合強大 (curl ... | jq ...) |
| Web 請求、API 客戶端、高併發爬蟲 | PHP cURL 擴展 / Guzzle | 效能、穩定、功能全,Guzzle 還提供 PSR-7/18、中介軟體、異步 |
| 環境禁用 cURL 擴展、極簡虛擬主機 | 命令行 curl + shell_exec | 兜底方案,注意 `escapeshellarg` 防注入 |
| 需 HTTP/3 (QUIC)、Unix Socket、多路複用 | PHP cURL (libcurl ≥ 7.66) / Swoole Hook | 命令行工具參數滯後,庫 API 最新特性優先支援 |
<?php
$urls = ['https://api.a.com', 'https://api.b.com', 'https://api.c.com'];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]);
curl_multi_add_handle($mh, $ch);
$handles[$url] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh, 0.1); // 避免忙等待
} while ($running);
$results = [];
foreach ($handles as $url => $ch) {
$results[$url] = [
'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'body' => curl_multi_getcontent($ch),
'err' => curl_error($ch),
];
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
<?php
$url = 'https://example.com/large.iso';
$localPath = '/data/large.iso';
$fp = fopen($localPath, 'ab'); // 追寫模式
$downloaded = filesize($localPath);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_FILE => $fp,
CURLOPT_RESUME_FROM => $downloaded, // 關鍵:從斷點續傳
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_NOPROGRESS => false,
CURLOPT_PROGRESSFUNCTION => function ($ch, $dltotal, $dlnow) {
printf("\rProgress: %.2f%%", $dlnow / $dltotal * 100);
},
]);
curl_exec($ch);
fclose($fp);
curl_close($ch);
CURLOPT_SSL_VERIFYPEER => true + CURLOPT_CAINFO 指定可信 CA 憑證包。CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS 禁用 file://、ftp:// 等危險協議 (防 SSRF)。CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS 限制重定向協議。CURLOPT_MAXREDIRS => 5 防無限重定向。CURLOPT_TIMEOUT / CURLOPT_CONNECTTIMEOUT 雙超時保護。cURL 是「面向人」的工具,libcurl 是「面向程式」的庫。 PHP 開發中,永遠優先使用 cURL 擴展 (或基於其封裝的 Guzzle/Symfony HttpClient),僅在極受限環境或運維腳本中退而求其次調用命令行工具。深入掌握 `curl_multi`、流式處理、安全選項,能讓你的 HTTP 客戶端從「能跑通」進化為「生產級可靠」。