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

PHP cURL 模擬表單 GET/POST 提交的封裝類實作

     編輯:PHP 綜合知識

在 API 串接、爬蟲、第三方支付回調測試等場景,常需模擬瀏覽器表單提交。本文提供一個乾淨、可復用的 SimulantForm 類,支援陣列/字串雙模式資料、Cookie 持久化、錯誤處理,開箱即用。

完整類別代碼

<?php

class SimulantForm
{
    protected string $url;
    protected $ch;
    protected array $defaultOptions = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 5,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_SSL_VERIFYPEER => false, // 僅測試環境建議關閉
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; SimulantForm/1.0)',
    ];

    public function __construct(string $url)
    {
        $this->url = $url;
        $this->ch = curl_init();
        $this->setOptions($this->defaultOptions);
        curl_setopt($this->ch, CURLOPT_URL, $url);
    }

    /** GET 請求:自動將陣列轉為 query string 附加至 URL */
    public function get($data = ''): string
    {
        $query = $this->buildQuery($data);
        $this->setOption(CURLOPT_URL, $this->url . $query);
        $this->setOption(CURLOPT_HTTPGET, true);
        return $this->execute();
    }

    /** POST 請求:支援陣列(multipart/form-data)或字串 */
    public function post($data): string
    {
        $this->setOption(CURLOPT_POST, true);
        $this->setOption(CURLOPT_POSTFIELDS, $data);
        $this->setOption(CURLOPT_URL, $this->url); // 確保 URL 乾淨
        return $this->execute();
    }

    /** 設定 Cookie 檔案(讀取/寫入)實現會話保持 */
    public function setCookieFile(string $file): void
    {
        $this->setOption(CURLOPT_COOKIEFILE, $file);
        $this->setOption(CURLOPT_COOKIEJAR, $file);
    }

    /** 取得最後一次請求的錯誤資訊 */
    public function getLastError(): array
    {
        return [curl_errno($this->ch), curl_error($this->ch)];
    }

    /** 取得 HTTP 狀態碼 */
    public function getHttpCode(): int
    {
        return (int)curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
    }

    /** 批次設定選項 */
    protected function setOptions(array $options): void
    {
        curl_setopt_array($this->ch, $options);
    }

    protected function setOption(int $option, $value): void
    {
        curl_setopt($this->ch, $option, $value);
    }

    /** 將陣列轉為 URL query string,支援多值鍵 foo[]=1&foo[]=2 */
    protected function buildQuery($data): string
    {
        if (empty($data)) return '';
        if (is_string($data)) return (strpos($data, '?') === 0 ? '' : '?') . $data;

        $parts = [];
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $v) {
                    $parts[] = urlencode($key) . '[]=' . urlencode($v);
                }
            } else {
                $parts[] = urlencode($key) . '=' . urlencode($value);
            }
        }
        return '?' . implode('&', $parts);
    }

    /** 執行請求並關閉 handle */
    protected function execute(): string
    {
        $response = curl_exec($this->ch);
        curl_close($this->ch);
        return $response ?: '';
    }

    /** 解構時確保資源釋放 */
    public function __destruct()
    {
        if (is_resource($this->ch)) curl_close($this->ch);
    }
}

使用範例

1. 簡單 GET 請求

$form = new SimulantForm('https://httpbin.org/get');
$html = $form->get(['q' => 'php curl', 'page' => 2]);
echo $html;

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

$form = new SimulantForm('https://httpbin.org/post');
$result = $form->post([
    'username' => 'demo',
    'password' => 'secret',
    'tags'     => ['php', 'curl', 'form'],
]);
print_r(json_decode($result, true));

3. 檔案上傳(multipart/form-data)

$form = new SimulantForm('https://api.example.com/upload');
$result = $form->post([
    'file' => new CURLFile('/path/to/image.jpg', 'image/jpeg', 'avatar.jpg'),
    'folder' => 'avatars',
]);

4. 維持登入狀態(Cookie 持久化)

$cookieFile = sys_get_temp_dir() . '/simulant_cookies.txt';

// 步驟 1:登入
$login = new SimulantForm('https://example.com/login');
$login->setCookieFile($cookieFile);
$login->post(['email' => 'user@test.com', 'pwd' => '123456']);

// 步驟 2:訪問需登入頁面
$dashboard = new SimulantForm('https://example.com/dashboard');
$dashboard->setCookieFile($cookieFile);
echo $dashboard->get();

關鍵設計細節

  • 資源管理:建構子初始化 curl_init(),execute() 結束時關閉,__destruct() 雙重保障避免洩漏。
  • 編碼安全:buildQuery() 統一使用 urlencode(),正確處理中文、特殊符號與多值陣列。
  • 彈性資料格式:POST 欄位直接透傳給 CURLOPT_POSTFIELDS,陣列自動編碼為 multipart/form-data,字串則作為 application/x-www-form-urlencoded。
  • 錯誤可觀測:提供 getLastError() 與 getHttpCode() 便於除錯與重試邏輯。

將此類納入專案共用函式庫,即可在任何需要模擬 HTTP 表單提交的場合一行代碼解決,專注於業務邏輯而非 cURL 參數細節。

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