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

PHP cURL 封裝類實戰指南:兩款高效網絡請求工具詳解

     編輯:PHP 綜合知識

前言

在 PHP 開發中,cURL 是進行 HTTP 請求的核心工具。雖然原生 cURL 函數功能強大,但直接使用往往代碼冗長、參數配置繁瑣。本文將介紹兩款實用的 PHP cURL 封裝類,幫助開發者輕鬆應對各種網絡請求場景,從基礎的 GET/POST 到複雜的 Header 設定、Cookie 管理、代理 IP 偽裝等高級功能。

環境準備:啟用 PHP cURL 擴展

在使用封裝類之前,必須確保 PHP 環境已正確載入 cURL 模組。Windows 環境下的啟用步驟如下:

  1. 打開 php.ini,找到 ;extension=php_curl.dll 並移除前面的分號
  2. 將 libeay32.dll、ssleay32.dll、php5ts.dll、php_curl.dll 複製到系統目錄 C:\Windows\ 下
  3. 重啟 Apache 服務使配置生效

可通過 phpinfo() 檢查 curl 區塊是否出現,確認擴展已成功載入。

封裝類一:支援完整 cURL 選項陣列的靈活類

這款封裝類採用陣列方式傳遞所有 cURL 選項,靈活度極高,適合需要精細控制請求參數的場景。

核心類代碼

<?php
class Curl
{
    public $cookieFile;
    public $timeout = 160;

    public function __construct($dir)
    {
        $this->cookieFile = $this->getTemporaryCookieFileName($dir);
    }

    /**
     * 發送請求並獲取響應內容
     * @param array $curlOptions cURL 選項陣列
     * @return string|false 成功返回響應字符串,失敗返回 false
     */
    public function getResponseText($curlOptions)
    {
        // 確保返回字符串而非直接輸出
        if (!isset($curlOptions[CURLOPT_RETURNTRANSFER]) || $curlOptions[CURLOPT_RETURNTRANSFER] === false) {
            $curlOptions[CURLOPT_RETURNTRANSFER] = true;
        }

        $curl = curl_init();
        curl_setopt_array($curl, $curlOptions);

        $responseText = '';
        try {
            $responseText = curl_exec($curl);
            if (($errno = curl_errno($curl)) !== CURLE_OK) {
                $errmsg = curl_error($curl);
                throw new Exception($errmsg, $errno);
            }
        } catch (Exception $e) {
            $responseText = false;
        }

        curl_close($curl);
        return $responseText;
    }

    /**
     * Unicode 轉 UTF-8 工具方法
     */
    public function unicodeToUtf8($string)
    {
        $string = str_replace('u', '', strtolower($string));
        $length = strlen($string) / 4;
        $stringResult = '';
        for ($i = 0; $i < $length; $i++) {
            $charUnicodeHex = substr($string, $i * 4, 4);
            $unicodeCode = hexdec($charUnicodeHex);
            $utf8Code = '';
            if ($unicodeCode < 128) {
                $utf8Code = chr($unicodeCode);
            } elseif ($unicodeCode < 2048) {
                $utf8Code .= chr(192 + (($unicodeCode - ($unicodeCode % 64)) / 64));
                $utf8Code .= chr(128 + ($unicodeCode % 64));
            } else {
                $utf8Code .= chr(224 + (($unicodeCode - ($unicodeCode % 4096)) / 4096));
                $utf8Code .= chr(128 + ((($unicodeCode % 4096) - ($unicodeCode % 64)) / 64));
                $utf8Code .= chr(128 + ($unicodeCode % 64));
            }
            $stringResult .= $utf8Code;
        }
        return $stringResult;
    }

    private function getTemporaryCookieFileName($dir = '.')
    {
        return str_replace('\\', '/', tempnam($dir, 'tmp'));
    }
}
?>

實際調用範例

<?php
include_once('curl.class.php');
$aa = new Curl('');

$curlOptions = array(
    CURLOPT_URL => "https://www.example.com/addTicket.jsp",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_REFERER => "https://www.example.com/referer",
    CURLOPT_HTTPHEADER => array(
        '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_HEADER => 1,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => 'ids=897&Submit=%E6%8A%95%E7%A5%A8',
    CURLOPT_TIMEOUT => $aa->timeout
);

echo $aa->getResponseText($curlOptions);
?>

關鍵特性:

  • 支援所有原生 cURL 選項,靈活性極高
  • 內建 Cookie 文件自動管理
  • 支援自定義 HTTP Header,可偽裝代理 IP、User-Agent 等
  • 異常捕獲機制,失敗時返回 false 而非拋出錯誤
  • 附帶 Unicode 轉 UTF-8 工具方法,處理編碼問題

封裝類二:語義化方法鏈風格的簡潔類

這款封裝類提供 get()、post()、put() 等語義化方法,代碼更易讀,適合快速開發常規 API 請求。

核心類代碼

<?php
class Curl
{
    function __construct() { return true; }

    function execute($method, $url, $fields = '', $userAgent = '', $httpHeaders = '', $username = '', $password = '')
    {
        $ch = self::create();
        if ($ch === false) return false;

        if (!is_string($url) || !strlen($url)) return false;

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        if ($username !== '') {
            curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
        }

        $method = strtolower($method);
        if ('post' === $method) {
            curl_setopt($ch, CURLOPT_POST, true);
            if (is_array($fields)) {
                $sets = array();
                foreach ($fields as $key => $val) {
                    $sets[] = $key . '=' . urlencode($val);
                }
                $fields = implode('&', $sets);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
        } elseif ('put' === $method) {
            curl_setopt($ch, CURLOPT_PUT, true);
        }

        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        if (strlen($userAgent)) {
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
        }
        if (is_array($httpHeaders)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
        }

        $ret = curl_exec($ch);
        if (curl_errno($ch)) {
            $err = array(curl_error($ch), curl_errno($ch));
            curl_close($ch);
            return $err;
        } else {
            curl_close($ch);
            if (!is_string($ret) || !strlen($ret)) return false;
            return $ret;
        }
    }

    function post($url, $fields, $userAgent = '', $httpHeaders = '', $username = '', $password = '')
    {
        $ret = self::execute('POST', $url, $fields, $userAgent, $httpHeaders, $username, $password);
        return ($ret === false || is_array($ret)) ? false : $ret;
    }

    function get($url, $userAgent = '', $httpHeaders = '', $username = '', $password = '')
    {
        $ret = self::execute('GET', $url, '', $userAgent, $httpHeaders, $username, $password);
        return ($ret === false || is_array($ret)) ? false : $ret;
    }

    function create()
    {
        if (!function_exists('curl_init')) return false;
        $ch = curl_init();
        return is_resource($ch) ? $ch : false;
    }
}
?>

調用範例

<?php
$curl = new Curl();

// GET 請求
$response = $curl->get('https://www.example.com/');

// POST 請求
$response = $curl->post('https://www.example.com/api', 'param1=value1&param2=value2');

// 帶 Header 的 POST
$headers = array('Content-Type: application/json', 'Authorization: Bearer token123');
$response = $curl->post('https://www.example.com/api', json_encode($data), '', $headers);
?>

優勢:

  • 方法命名直觀,符合 REST 風格
  • 自動處理陣列轉查詢字符串
  • 支援基本認證
  • 統一的錯誤處理返回格式

兩款封裝類對比與選型建議

特性封裝類一(選項陣列)封裝類二(語義化方法)
靈活度極高,支援所有 cURL 選項中等,封裝常用場景
代碼可讀性需熟悉 cURL 選項常量高,方法名語義清晰
適用場景複雜請求、特殊 Header、代理、SSL 設定常規 REST API、快速原型開發
Cookie 管理內建臨時文件自動管理需自行擴展
錯誤處理try-catch 異常捕獲返回 false 或錯誤陣列

最佳實踐建議

  1. 超時設定:生產環境務必設定 CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT,防止請求無限等待
  2. SSL 驗證:開發環境可暫時關閉 CURLOPT_SSL_VERIFYPEER,生產環境建議配置 CA 憑證啟用驗證
  3. User-Agent:設定合理的 User-Agent,避免被目標服務器識別為機器人而拒絕
  4. 錯誤日誌:將失敗請求的 URL、錯誤碼、錯誤信息記錄日誌,便於排查
  5. 複用連接:高頻請求同一域名時,考慮啟用 CURLOPT_TCP_KEEPALIVE 或使用 cURL 多工

總結

cURL 封裝類能顯著提升 PHP 網絡請求的開發效率與代碼維護性。封裝類一適合需要精細控制的複雜場景,封裝類二適合日常 API 對接。根據項目需求選擇合適的封裝,並遵循最佳實踐,即可構建健壯的 HTTP 客戶端。

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