首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP cURL 完全指南:從入門到避坑的 7 大實戰場景

     編輯:PHP 綜合知識

cURL 是什麼?

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. 關閉

場景 1:GET 請求 + HTTPS

$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)。僅在開發環境自簽證書時臨時關閉,並添加註釋說明風險。

場景 2:POST 表單數據

$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);

場景 3:POST JSON 數據

$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);

場景 4:文件上傳(PHP 5.6+ CURLFile)

$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,否則靜默失敗。

場景 5:文件下載(流式寫入,大文件不佔內存)

$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('下載不完整');
}

場景 6:HTTP Basic 認證

$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);

場景 7:Cookie 會話保持(模擬登錄)

$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);

調試神器:curl_getinfo()

$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 流式讀取
重定向丟失 HeaderCURLOPT_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 版

高級:封裝通用 HttpClient

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() 等語義化方法,並接入日志、監控、熔斷器,構建健壯的服務間通訊層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved