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

PHP 獲取 POST 資料完整指南:三種方法原理、適用場景與最佳實踐

     編輯:PHP 相關知識

PHP 接收 POST 資料不僅限於 $_POST。根據 Content-Type 與資料格式,需選擇正確方式才能完整獲取原始資料。本文系統整理三種核心方法、適用場景、陷阱與實戰範例。

三大核心方法對比

方法適用 Content-Type特點限制
$_POST['field']application/x-www-form-urlencoded
multipart/form-data
自動解析、鍵值陣列、最常用僅支援表單格式,無法獲取 JSON、XML、原始二進位
file_get_contents('php://input')所有類型(除 multipart/form-data)獲取原始 Body、記憶體效率高、無需 php.ini 設定無法處理檔案上傳(multipart)
$GLOBALS['HTTP_RAW_POST_DATA']非 PHP 識別的 MIME 類型舊版相容、獲取原始資料需 always_populate_raw_post_data=-1 (PHP 5.6+)
PHP 7.0+ 已移除

方法 1:$_POST — 標準表單處理

<form method="POST" action="handler.php" enctype="application/x-www-form-urlencoded">
  <input name="username">
  <input name="password" type="password">
</form>

// handler.php
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';

適用:傳統 HTML 表單、AJAX application/x-www-form-urlencoded、multipart/form-data(檔案上傳另用 $_FILES)。

方法 2:php://input — 通用原始資料讀取(推薦)

$raw = file_get_contents('php://input');
// JSON API
$data = json_decode($raw, true);
// XML API
$xml = simplexml_load_string($raw);
// 純文字/二進位
processBinary($raw);

優勢:

  • 支援 application/json、application/xml、text/plain、application/octet-stream 等
  • 記憶體佔用比 $HTTP_RAW_POST_DATA 低
  • 無需 php.ini 設定
  • 可多次讀取(PHP 5.6+ 為不可重讀串流,建議變數暫存)

注意:enctype="multipart/form-data" 時 php://input 為空,需用 $_POST + $_FILES。

方法 3:$HTTP_RAW_POST_DATA — 歷史遺留(已棄用)

// php.ini 需設定
always_populate_raw_post_data = -1  // PHP 5.6+ 不產生預設變數,避免警告

$raw = $GLOBALS['HTTP_RAW_POST_DATA'];
// 僅在 Content-Type 非表單類型時可用

現狀:PHP 7.0 完全移除,**嚴禁新專案使用**。

實戰場景:微信企業號/公眾號 XML 訊息接收

<?php
// 接收微信回調 POST 的 XML
$rawXml = file_get_contents('php://input');
if (empty($rawXml)) { exit('empty'); }

// 解析 XML(防 XXE 攻擊)
libxml_disable_entity_loader(true);
$xml = simplexml_load_string($rawXml, 'SimpleXMLElement', LIBXML_NOCDATA);

$msgType = (string)$xml->MsgType;
$fromUser = (string)$xml->FromUserName;
$content = (string)$xml->Content;

// 業務邏輯...
echo generateReplyXml($fromUser, $xml->ToUserName, 'text', '收到:' . $content);

進階:統一封裝 Request 物件

class HttpRequest {
    public static function all(): array {
        $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
        
        // JSON API
        if (strpos($contentType, 'application/json') !== false) {
            $raw = file_get_contents('php://input');
            return json_decode($raw, true) ?? [];
        }
        
        // XML / 純文字 / 其他
        if (in_array($contentType, ['application/xml', 'text/xml', 'text/plain'], true)) {
            return ['raw' => file_get_contents('php://input')];
        }
        
        // 標準表單
        return $_POST;
    }
    
    public static function raw(): string {
        return file_get_contents('php://input');
    }
}

// 使用
$data = HttpRequest::all();
$rawXml = HttpRequest::raw();

常見坑點速查

$_POST 為空但確定有資料送達
檢查 Content-Type 是否為 application/json 等非表單類型,改用 php://input
檔案上傳 $_POST 沒有檔案資訊
檔案在 $_FILES,表單欄位在 $_POST
php://input 只能讀一次
PHP 5.6+ 為不可重讀串流,首次讀取即存入變數複用
大檔案導致記憶體耗盡
改用串流處理:fopen('php://input', 'r') 分塊讀取

最佳實踐總結

  1. 標準表單:直接用 $_POST / $_FILES
  2. API(JSON/XML/自訂格式):統一用 file_get_contents('php://input')
  3. 封裝統一入口:建立 Request 類別,屏蔽底層差異
  4. 棄用 $HTTP_RAW_POST_DATA:PHP 7+ 不相容
  5. 安全性:XML 解析必須停用外部實體(libxml_disable_entity_loader(true))

掌握三種方法的適用邊界,能讓你在傳統表單、現代 API、第三方回調等場景游刃有餘。

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