PHP 接收 POST 資料不僅限於 $_POST。根據 Content-Type 與資料格式,需選擇正確方式才能完整獲取原始資料。本文系統整理三種核心方法、適用場景、陷阱與實戰範例。
| 方法 | 適用 Content-Type | 特點 | 限制 |
|---|---|---|---|
$_POST['field'] | application/x-www-form-urlencodedmultipart/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+ 已移除 |
<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)。
$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 設定注意:enctype="multipart/form-data" 時 php://input 為空,需用 $_POST + $_FILES。
// php.ini 需設定
always_populate_raw_post_data = -1 // PHP 5.6+ 不產生預設變數,避免警告
$raw = $GLOBALS['HTTP_RAW_POST_DATA'];
// 僅在 Content-Type 非表單類型時可用
現狀:PHP 7.0 完全移除,**嚴禁新專案使用**。
<?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);
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,表單欄位在 $_POSTphp://input 只能讀一次fopen('php://input', 'r') 分塊讀取$_POST / $_FILESfile_get_contents('php://input')Request 類別,屏蔽底層差異$HTTP_RAW_POST_DATA:PHP 7+ 不相容libxml_disable_entity_loader(true))掌握三種方法的適用邊界,能讓你在傳統表單、現代 API、第三方回調等場景游刃有餘。