cURL 是 PHP 處理 HTTP 請求的核心擴充,封裝為可復用類別能統一錯誤處理、超時控制、Cookie 管理、Header 構建。本文提供兩種成熟封裝架構:選項陣列注入模式與鏈式方法模式,涵蓋 GET/POST/PUT、SSL、代理、偽造 IP 等實戰場景。
# php.ini 啟用
extension=curl
# 依賴庫(Windows 需放入 System32)
libeay32.dll, ssleay32.dll, php_curl.dll
<?php
class CurlClient {
public string $cookieFile;
public int $timeout = 160;
public function __construct(string $cookieDir = '') {
$this->cookieFile = $cookieDir
? sys_get_temp_dir() . '/curl_cookie_' . md5($cookieDir) . '.txt'
: tempnam(sys_get_temp_dir(), 'curl_cookie_');
}
/**
* 發送請求並回傳回應內容
* @param array $options CURLOPT_* 常數鍵值陣列
* @return string|false 成功回傳字串,失敗回傳 false
*/
public function request(array $options): string|false {
// 1. 強制啟用回傳字串
$options[CURLOPT_RETURNTRANSFER] = true;
// 2. 自動處理 Cookie 持久化
if (!isset($options[CURLOPT_COOKIEFILE])) {
$options[CURLOPT_COOKIEFILE] = $this->cookieFile;
$options[CURLOPT_COOKIEJAR] = $this->cookieFile;
}
$ch = curl_init();
curl_setopt_array($ch, $options);
try {
$response = curl_exec($ch);
if ($response === false) {
throw new \Exception(curl_error($ch), curl_errno($ch));
}
return $response;
} catch (\Exception $e) {
error_log('[CurlClient] ' . $e->getMessage());
return false;
} finally {
curl_close($ch);
}
}
// Unicode 轉 UTF-8 工具方法
public static function unicodeToUtf8(string $str): string {
$str = str_replace('\\u', '', strtolower($str));
$out = '';
for ($i = 0, $len = strlen($str); $i < $len; $i += 4) {
$hex = substr($str, $i, 4);
$code = hexdec($hex);
if ($code < 128) $out .= chr($code);
elseif ($code < 2048) $out .= chr(192 | ($code >> 6)) . chr(128 | ($code & 63));
else $out .= chr(224 | ($code >> 12)) . chr(128 | (($code >> 6) & 63)) . chr(128 | ($code & 63));
}
return $out;
}
}
// === 使用範例:POST 請求偽造 Header 與 IP ===
$client = new CurlClient();
$options = [
CURLOPT_URL => 'https://api.example.com/ticket',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => 'ids=897&Submit=%E6%8A%95%E7%A5%A8',
CURLOPT_HTTPHEADER => [
'X-FORWARDED-FOR: 139.197.14.19',
'CLIENT-IP: 127.0.0.1',
'Proxy-Client-IP: 139.197.14.19',
'WL-Proxy-Client-IP: 139.197.14.19',
],
CURLOPT_REFERER => 'https://www.example.com/referer',
CURLOPT_HEADER => true, // 回傳包含 Header
CURLOPT_TIMEOUT => $client->timeout,
CURLOPT_SSL_VERIFYPEER => false, // 僅測試環境關閉驗證
];
$response = $client->request($options);
if ($response !== false) {
echo $response;
}
?>
<?php
class SimpleCurl {
private $ch;
private array $headers = [];
private array $postFields = [];
private string $method = 'GET';
private int $timeout = 10;
public function __construct() {
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_HEADER, false);
curl_setopt($this->ch, CURLOPT_TIMEOUT, $this->timeout);
}
public function url(string $url): self {
curl_setopt($this->ch, CURLOPT_URL, $url);
return $this;
}
public function method(string $method): self {
$this->method = strtoupper($method);
return $this;
}
public function header(string $key, string $value): self {
$this->headers[] = "$key: $value";
return $this;
}
public function headers(array $headers): self {
foreach ($headers as $k => $v) $this->header($k, $v);
return $this;
}
public function data(array|string $data): self {
if (is_array($data)) {
$data = http_build_query($data);
}
$this->postFields = $data;
if ($this->method === 'POST') {
curl_setopt($this->ch, CURLOPT_POST, true);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
}
return $this;
}
public function timeout(int $seconds): self {
curl_setopt($this->ch, CURLOPT_TIMEOUT, $seconds);
return $this;
}
public function exec(): string|false {
if ($this->headers) {
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->headers);
}
$response = curl_exec($this->ch);
if ($response === false) {
error_log('[SimpleCurl] ' . curl_error($this->ch));
return false;
}
return $response;
}
public function __destruct() {
if (is_resource($this->ch)) curl_close($this->ch);
}
}
// === 使用範例 ===
$curl = new SimpleCurl();
$response = $curl->url('https://api.example.com/users')
->method('POST')
->header('Authorization', 'Bearer token123')
->header('Content-Type', 'application/json')
->data(['name' => 'John', 'email' => 'john@example.com'])
->timeout(15)
->exec();
if ($response) {
$data = json_decode($response, true);
print_r($data);
}
?>
| 常數 | 用途 | 典型值 |
|---|---|---|
CURLOPT_URL | 請求網址 | 字串 |
CURLOPT_RETURNTRANSFER | 回傳字串而非直接輸出 | true |
CURLOPT_POST | 啟用 POST | true |
CURLOPT_POSTFIELDS | POST 資料 | 字串或陣列(自動 multipart/form-data) |
CURLOPT_HTTPHEADER | 自訂 Header | ['Key: Value', ...] |
CURLOPT_COOKIEFILE/JAR | Cookie 讀寫檔案 | 檔案路徑 |
CURLOPT_SSL_VERIFYPEER | 驗證 SSL 憑證 | false (測試) / true (生產) |
CURLOPT_TIMEOUT | 最大執行秒數 | 整數 |
CURLOPT_PROXY | 代理伺服器 | 'ip:port' |
CURLOPT_USERAGENT | 偽造 UA | 字串 |
CURLOPT_SSL_VERIFYPEER => true 並配合 CURLOPT_CAINFO 指定 CA 憑證包。Content-Type: application/x-www-form-urlencoded; charset=utf-8,回應以 mb_convert_encoding() 處理。CURLOPT_INFILE + CURLOPT_UPLOAD 流式傳輸,避免記憶體爆炸。curl_multi_* 系列函式或 GuzzleHttp 等成熟庫。封裝 cURL 類別能將 HTTP 通訊細節內聚,業務代碼專注於參數組裝與回應解析,是 PHP 後端開發的基礎設施建設核心環節。