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

PHP cURL 基礎操作詳解:從入門到實戰

     編輯:PHP 相關知識

cURL 是 PHP 與外部服務交互的核心工具,支援 HTTP/HTTPS/FTP/IMAP/POP3/SMTP 等協議,功能遠超 `file_get_contents()`。本文涵蓋安裝啟用、基礎四步法、常用選項速查表、GET/POST/JSON/文件上傳/代理/SSL/異步並發等實戰場景完整代碼。

一、環境啟用

; php.ini
extension=curl ; 取消註釋
; Windows: extension_dir = "ext" 確認 php_curl.dll 存在
; Linux: apt/yum install php-curl && systemctl restart php-fpm

驗證:`php -m | grep curl` 或 `php -r "var_dump(curl_version());"`

二、基礎四步法

<?php
// 1. 初始化
$ch = curl_init();

// 2. 設置選項 (核心)
curl_setopt_array($ch, [
    CURLOPT_URL            => 'https://api.example.com/users',
    CURLOPT_RETURNTRANSFER => true,      // 返回字串而非直接輸出
    CURLOPT_HEADER         => false,     // 不包含響應頭
    CURLOPT_TIMEOUT        => 10,        // 總超時秒數
    CURLOPT_CONNECTTIMEOUT => 5,         // 連接超時
    CURLOPT_SSL_VERIFYPEER => true,      // 生產環境必須驗證 SSL 證書
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_FOLLOWLOCATION => true,      // 跟隨重定向
    CURLOPT_MAXREDIRS      => 5,
    CURLOPT_USERAGENT      => 'MyApp/1.0 (+https://my.com)', // 良好的公民
]);

// 3. 執行並獲取結果
$response = curl_exec($ch);

// 4. 錯誤處理
if ($response === false) {
    $errno = curl_errno($ch);
    $error = curl_error($ch);
    curl_close($ch);
    throw new RuntimeException("cURL Error [$errno]: $error");
}

// 5. 獲取響應信息 (可選)
$info = curl_getinfo($ch);
$httpCode = $info['http_code']; // 200, 404, 500...

// 6. 關閉釋放資源
curl_close($ch);

// 處理響應
$data = json_decode($response, true);
?>

三、常用選項速查表 (按場景分類)

四、實戰場景代碼模板

1. GET 請求帶參數

<?php
$params = ['page' => 1, 'limit' => 20, 'keyword' => 'php'];
$url = 'https://api.example.com/search?' . http_build_query($params);

$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true]);
$response = curl_exec($ch);
curl_close($ch);
?>

2. POST 表單提交 (application/x-www-form-urlencoded)

<?php
$postData = ['username' => 'admin', 'password' => 'secret'];
$ch = curl_init('https://api.example.com/login');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query($postData), // 自動設置 Content-Type
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
?>

3. POST JSON API (application/json)

<?php
$payload = ['order_id' => '20240101001', 'amount' => 99.9, 'items' => [['sku' => 'A1', 'qty' => 2]]];
$ch = curl_init('https://api.example.com/orders');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json', 'Accept: application/json'],
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
?>

4. 文件上傳 (multipart/form-data)

<?php
// PHP 5.5+ 使用 CURLFile (舊版 @/path 已棄用)
$filePath = '/path/to/image.png';
$cfile = new CURLFile($filePath, 'image/png', 'avatar.png');

$postData = [
    'user_id' => 123,
    'avatar'  => $cfile, // 鍵名對應服務端 $_FILES['avatar']
];

$ch = curl_init('https://api.example.com/upload');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $postData, // 陣列自動 multipart
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
?>

5. Bearer Token 認證 (OAuth2/JWT)

<?php
$accessToken = 'eyJhbGciOiJIUzI1NiIs...';
$ch = curl_init('https://api.example.com/me');
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $accessToken],
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
?>

6. 並發請求 (curl_multi_* 批量併發)

<?php
$urls = [
    'https://api1.example.com/data',
    'https://api2.example.com/data',
    'https://api3.example.com/data',
];

$mh = curl_multi_init();
$handles = [];

foreach ($urls as $i => $url) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]);
    curl_multi_add_handle($mh, $ch);
    $handles[$i] = $ch;
}

$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh, 0.5); // 等待活動
} while ($running > 0);

$results = [];
foreach ($handles as $i => $ch) {
    $results[$i] = [
        'response' => curl_multi_getcontent($ch),
        'info'     => curl_getinfo($ch),
        'error'    => curl_error($ch),
    ];
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}
curl_multi_close($mh);

print_r($results);
?>

7. 斷點續傳大文件下載

<?php
$url = 'https://speed.hetzner.de/100MB.bin';
$savePath = '/tmp/100MB.bin';
$fp = fopen($savePath, 'ab'); // 追加模式
$fileSize = filesize($savePath) ?: 0;

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_FILE           => $fp,
    CURLOPT_RANGE          => $fileSize . '-', // 從斷點續傳
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 0, // 不限制總時間
    CURLOPT_LOW_SPEED_LIMIT => 1024,
    CURLOPT_LOW_SPEED_TIME => 30,
]);
curl_exec($ch);
curl_close($ch);
fclose($fp);
?>

五、錯誤碼對照與調試技巧

場景選項說明
基礎CURLOPT_URL請求地址
CURLOPT_RETURNTRANSFERtrue 返回字串,false 直接輸出
CURLOPT_HEADERtrue 包含響應頭
超時CURLOPT_TIMEOUT整個請求最大秒數
CURLOPT_CONNECTTIMEOUT建立連接最大秒數
CURLOPT_LOW_SPEED_LIMIT低速限制字節/秒
CURLOPT_LOW_SPEED_TIME低速持續秒數觸發中止
SSLCURLOPT_SSL_VERIFYPEER驗證證書 (生產 true)
CURLOPT_SSL_VERIFYHOST2 驗證 CN 匹配域名
CURLOPT_CAINFO自定義 CA 憑證路徑
代理CURLOPT_PROXY代理地址 ip:port
CURLOPT_PROXYTYPECURLPROXY_HTTP/SOCKS5
CURLOPT_PROXYUSERPWD代理認證 user:pwd
CookieCURLOPT_COOKIE發送 Cookie 字串
CURLOPT_COOKIEJAR保存響應 Cookie 到文件
CURLOPT_COOKIEFILE從文件讀取 Cookie 發送
認證CURLOPT_USERPWDBasic Auth "user:pwd"
CURLOPT_HTTPAUTHCURLAUTH_BASIC/DIGEST/BEARER
CURLOPT_BEARERBearer Token (PHP 7.1+)
錯誤碼常量典型原因
6CURLE_COULDNT_RESOLVE_HOSTDNS 解析失敗
7CURLE_COULDNT_CONNECT連接被拒/防火牆/端口錯誤
28CURLE_OPERATION_TIMEDOUT超時 (調大 TIMEOUT/CONNECTTIMEOUT)
35CURLE_SSL_CONNECT_ERRORSSL 握手失敗 (證書過期/不信任/協議版本)
51CURLE_SSL_PEER_CERTIFICATE證書驗證失敗 (CA 不匹配/自簽名)
60CURLE_SSL_CACERTCA 證書文件找不到/格式錯誤

調試開啟詳細日誌

<?php
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_VERBOSE => true, // 輸出詳細通訊過程
    CURLOPT_STDERR  => fopen('php://temp', 'rw'), // 捕獲到變量
    CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
rewind($verbose = curl_getinfo($ch, CURLINFO_HEADER_OUT)); // 不對,正確捕獲:
// 正確捕獲 VERBOSE 輸出:
$verboseHandle = fopen('php://temp', 'rw');
curl_setopt($ch, CURLOPT_STDERR, $verboseHandle);
curl_exec($ch);
rewind($verboseHandle);
$verboseLog = stream_get_contents($verboseHandle);
fclose($verboseHandle);
error_log($verboseLog); // 記錄到日誌分析
?>

六、最佳實踐清單

  1. **生產環境強制驗證 SSL** (`CURLOPT_SSL_VERIFYPEER=true`),內網可配 `CURLOPT_CAINFO` 指定內部 CA。
  2. **設置合理超時**:連接 3-5s,總超時 10-30s,防止慢服務拖垮自身進程。
  3. **複用句柄**:高頻調用同一域名時,保持 `$ch` 復用,僅 `curl_setopt($ch, CURLOPT_URL, $newUrl)` 修改 URL,利用 Keep-Alive。
  4. **異常處理**:`curl_exec` 返回 `false` 時必須檢查 `curl_errno/error`,拋出具體異常。
  5. **限流與重試**:配合 Token Bucket 限流器,指數退避重試 (如 Guzzle Middleware / Symfony HttpClient)。
  6. **敏感信息脫敏**:日誌記錄 URL 時移除 `access_token`、`password` 等查詢參數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved