PHP 通過超全局陣列接收客戶端提交的資料,最常用的是 $_GET、$_POST、$_REQUEST。三者看似相似,實則在資料來源、安全性、性能、優先級上有本質區別。本文從底層機制到實戰建議全方位拆解。
| 特性 | $_GET | $_POST | $_REQUEST |
|---|---|---|---|
| 資料來源 | URL 查詢字串 ?a=1&b=2 | HTTP Body(表單 method="post") | 合併 $_GET、$_POST、$_COOKIE |
| 可見性 | 地址欄明文可見 | 不顯示在 URL | 同上 |
| 資料量限制 | ~2KB(瀏覽器/伺服器限制) | 理論無上限,受 post_max_size、upload_max_filesize 制約 | 同上 |
| 安全性 | 低(易被記錄、CSRF、洩露敏感資訊) | 較高(不在 URL、支援 CSRF Token) | 最低(混合來源,難以追蹤) |
| 性能 | 快 | 快 | 較慢(需合併三個陣列) |
| 適用場景 | 查詢、分頁、搜尋、可分享連結 | 新增、修改、刪除、登入、上傳 | 極少數需兼容新舊接口的過渡代碼 |
variables_order 決定合併優先級php.ini 中的 variables_order = "GPCS" 定義了 $_REQUEST 合併順序:
$_GET$_POST$_COOKIE$_SERVER後者覆蓋前者。預設 GPCS 意味著同名鍵值下:$_POST 覆蓋 $_GET,$_COOKIE 覆蓋 $_POST。
<?php
echo "GET:\n"; print_r($_GET);
echo "POST:\n"; print_r($_POST);
echo "REQUEST:\n"; print_r($_REQUEST);
?>
<form method="post" action="?a=1&b=2">
<input type="text" name="a" value="a">
<input type="text" name="b" value="b">
<input type="submit" value="test">
</form>
輸出結果:
GET:
Array ( [a] => 1 [b] => 2 )
POST:
Array ( [a] => a [b] => b )
REQUEST:
Array ( [a] => a [b] => b ) // POST 覆蓋 GET
結論:
$_GET$_POST$_REQUEST 取後者(POST 覆蓋 GET)$_GET 或 $_POST,避免 $_REQUEST 帶來的隱性 Bug。SameSite Cookie、CSRF Token 可有效防禦 CSRF。variables_order 中 C 在 P 後)。$_GET;寫入/登入/上傳 → $_POST。filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) 等內建過濾器,而非直接 $_GET['id']。$_POST['_token'] === $_SESSION['_token']。post_max_size = 8M、upload_max_filesize = 2M 按業務調整。若業務必須在 action 帶查詢參數(如 /save?type=article),同時 POST 表單提交:
$_GET['type'] 讀取$_POST['title'] 讀取$_REQUEST$_GET、$_POST、$_REQUEST 的區別本質是 HTTP 協議層面的「查詢字串」vs「請求體」vs「混合來源」。堅持「顯式優於隱式」,根據語義選擇 $_GET 或 $_POST,徹底拒絕 $_REQUEST,是寫出安全、可維護 PHP 代碼的基礎功力。