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

PHP 發送 POST 請求的輕量級實現:基於 Stream Context 的完整範例

     編輯:PHP 綜合知識

核心函數:do_post_request()

這個函數利用 PHP 內建的 stream_context_create() 與 fopen() 實現 HTTP POST 請求,無需依賴 cURL 擴展,適合簡單場景或受限環境。

/**
 * 發送 HTTP POST 請求
 *
 * @param string $url      目標 URL
 * @param string $data     已編碼的 POST 資料(application/x-www-form-urlencoded 格式)
 * @param string|null $optional_headers 額外 HTTP 標頭,如 "Content-Type: application/json\r\nAuthorization: Bearer xxx"
 * @return string|false  回應內容,失敗拋出 Exception
 * @throws Exception       連線或讀取失敗時拋出
 */
function do_post_request($url, $data, $optional_headers = null) {
    // 建立 stream context 選項
    $params = [
        'http' => [
            'method'  => 'POST',
            'content' => $data,
        ]
    ];

    // 註入自訂標頭
    if ($optional_headers !== null) {
        $params['http']['header'] = $optional_headers;
    }

    // 建立 context 並開啟串流
    $ctx = stream_context_create($params);
    $fp = @fopen($url, 'rb', false, $ctx);
    
    if (!$fp) {
        throw new Exception("無法連線至 $url: " . $php_errormsg);
    }

    // 讀取回應
    $response = @stream_get_contents($fp);
    fclose($fp);

    if ($response === false) {
        throw new Exception("從 $url 讀取資料失敗: " . $php_errormsg);
    }

    return $response;
}

使用範例:發送 JSON 資料

注意:預設 Content-Type 為 application/x-www-form-urlencoded。若需發送 JSON,必須手動設定標頭並編碼資料。

// 1. 準備 JSON 字串
$json_payload = json_encode([
    'user_id' => 12345,
    'action'  => 'update_profile',
    'data'    => ['nickname' => '新用戶', 'email' => 'user@example.com']
]);

// 2. 設定標頭:指定 Content-Type 為 JSON
$headers = "Content-Type: application/json\r\n";
$headers .= "Content-Length: " . strlen($json_payload) . "\r\n";

// 3. 發送請求
try {
    $response = do_post_request('https://api.example.com/endpoint', $json_payload, $headers);
    $result = json_decode($response, true);
    
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception('回應非合法 JSON: ' . $response);
    }
    
    echo "API 回應: "; print_r($result);
} catch (Exception $e) {
    error_log("POST 請求失敗: " . $e->getMessage());
    echo "請求處理異常,請稍後再試。";
}

進階用法:表單資料發送

傳統表單提交格式(application/x-www-form-urlencoded)可直接使用 http_build_query() 編碼陣列:

$form_data = [
    'username' => 'user123',
    'password' => 'secret',
    'remember' => 1
];

$post_data = http_build_query($form_data); // 自動 URL 編碼

$response = do_post_request('https://example.com/login', $post_data);

優缺點分析與替代方案

維度Stream Context (本函數)cURL (curl_* 函數)Guzzle / HTTP Client 套件
依賴需求無(PHP 核心功能)需啟用 php_curl.dll/so需 Composer 安裝
功能豐富度基礎(支援 POST、標頭、基本 SSL)完整(多協定、並發、代理、認證、進階 SSL)極豐富(中介軟體、重試、異步、PSR-7/18 相容)
錯誤處理需自行 try/catch需檢查 curl_errno/error拋出具體異常類別
適用場景簡單請求、無 cURL 環境、輕量腳本生產環境標準選擇、複雜互動現代框架專案、微服務呼叫、長期維護專案

常見問題排查

  • HTTPS 失敗:確認 php.ini 已啟用 openssl 擴展,且 CA 憑證路徑正確(curl.cainfo 或 openssl.cafile)。
  • 超時控制:Stream context 預設無超時,可加入 'timeout' => 10(秒)於 $params['http'] 中。
  • 重導向處理:預設不跟隨重導向,需加入 'follow_location' => 1(PHP 5.3.4+)並設定 'max_redirects' => 5。
  • 大檔案上傳:不建議用此法,請改用 cURL 的 CURLOPT_INFILE 或分塊上傳。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved