cURL 是 PHP 進行 HTTP 通訊的瑞士軍刀,支援 GET/POST、HTTPS、代理、Cookie、檔案上傳、多執行緒並發等。本文系統整理核心函數、常用選項、四大經典實戰場景,並提供可直接落地的面向物件封裝類。
| 函數 | 用途 |
|---|---|
| curl_init() | 初始化會話,返回 handle |
| curl_setopt() / curl_setopt_array() | 設定單個/批量選項 |
| curl_exec() | 執行請求,返回回應(或直接輸出) |
| curl_getinfo() | 獲取最後一次傳輸資訊(HTTP 碼、耗時、大小等) |
| curl_error() / curl_errno() | 獲取錯誤訊息/代碼 |
| curl_close() | 關閉會話,釋放資源 |
| curl_multi_* 系列 | 並發多請求處理 |
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.example.com/endpoint',
CURLOPT_RETURNTRANSFER => true, // 返回字串而非直接輸出
CURLOPT_HEADER => false, // 不包含回應頭
CURLOPT_FOLLOWLOCATION => true, // 自動追蹤 3xx 重定向
CURLOPT_MAXREDIRS => 5, // 最大重定向次數
CURLOPT_TIMEOUT => 10, // 總超時秒數
CURLOPT_CONNECTTIMEOUT => 5, // 連線超時秒數
CURLOPT_SSL_VERIFYPEER => true, // 驗證 SSL 憑證(生產環境必開)
CURLOPT_SSL_VERIFYHOST => 2, // 驗證宿主名
CURLOPT_CAINFO => '/path/to/cacert.pem', // 自定 CA 憑證包
CURLOPT_USERAGENT => 'MyApp/1.0', // 自定 UA
CURLOPT_HTTPHEADER => [ // 自定請求頭
'Content-Type: application/json',
'Authorization: Bearer ' . $token,
],
CURLOPT_POST => true, // POST 請求
CURLOPT_POSTFIELDS => json_encode($data), // POST 資料
]);
?>
<?php
$ch = curl_init('https://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$html = curl_exec($ch);
if ($html === false) throw new Exception(curl_error($ch), curl_errno($ch));
curl_close($ch);
// 解析 $html...
?>
<?php
$data = ['phone' => '13800001111', 'msg' => 'Hello cURL'];
$ch = curl_init('https://sms.example.com/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data), // 表單格式
// CURLOPT_POSTFIELDS => json_encode($data), // JSON 格式需配合 Content-Type
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
]);
$resp = curl_exec($ch);
curl_close($ch);
?>
<?php
curl_setopt_array($ch, [
CURLOPT_PROXY => 'proxy.example.com:8080',
CURLOPT_PROXYUSERPWD => 'user:pass', // 若需認證
CURLOPT_PROXYTYPE => CURLPROXY_HTTP, // 或 SOCKS5
CURLOPT_HTTPPROXYTUNNEL => true, // HTTP CONNECT 隧道
]);
?>
<?php
$cookieJar = sys_get_temp_dir() . '/cookie_' . md5($url) . '.txt';
$ch = curl_init($loginUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => ['username' => $user, 'password' => $pass],
CURLOPT_COOKIEJAR => $cookieJar, // 登錄後儲存 Cookie
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
// 後續請求攜帶 Cookie
$ch = curl_init($protectedUrl);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieJar); // 讀取 Cookie
$content = curl_exec($ch);
curl_close($ch);
?>
<?php
class HttpClient {
private $ch;
private array $defaultOptions = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'PHP-HttpClient/1.0',
];
public function __construct() {
$this->ch = curl_init();
curl_setopt_array($this->ch, $this->defaultOptions);
}
public function get(string $url, array $headers = []): string {
return $this->request('GET', $url, null, $headers);
}
public function post(string $url, $data = null, array $headers = []): string {
return $this->request('POST', $url, $data, $headers);
}
public function request(string $method, string $url, $data = null, array $headers = []): string {
$opts = [
CURLOPT_URL => $url,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
];
if ($data !== null) {
$opts[CURLOPT_POSTFIELDS] = is_array($data) ? http_build_query($data) : $data;
}
curl_setopt_array($this->ch, $opts);
$resp = curl_exec($this->ch);
if ($resp === false) {
throw new \RuntimeException(curl_error($this->ch), curl_errno($this->ch));
}
return $resp;
}
public function getInfo(int $opt = 0) {
return $opt ? curl_getinfo($this->ch, $opt) : curl_getinfo($this->ch);
}
public function __destruct() {
if (is_resource($this->ch)) curl_close($this->ch);
}
}
// 使用示例
$client = new HttpClient();
$json = $client->post('https://api.example.com/users', ['name' => 'John'], [
'Content-Type: application/json',
'Authorization: Bearer token123'
]);
$data = json_decode($json, true);
echo "HTTP Code: " . $client->getInfo(CURLINFO_HTTP_CODE);
?>
curl_multi_* 或 Swoole/amphp 協程實現真正並發。CURLOPT_DNS_CACHE_TIMEOUT 減少解析開銷。CURLOPT_FORBID_REUSE 為 false。