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

PHP 超全局變量 $_GET、$_POST、$_REQUEST 差異深度解析與最佳實踐

     編輯:PHP 相關知識

PHP 通過超全局陣列接收客戶端提交的資料,最常用的是 $_GET、$_POST、$_REQUEST。三者看似相似,實則在資料來源、安全性、性能、優先級上有本質區別。本文從底層機制到實戰建議全方位拆解。

一、核心差異速覽表

特性$_GET$_POST$_REQUEST
資料來源URL 查詢字串 ?a=1&b=2HTTP 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 合併順序:

  1. G - $_GET
  2. P - $_POST
  3. C - $_COOKIE
  4. S - $_SERVER

後者覆蓋前者。預設 GPCS 意味著同名鍵值下:$_POST 覆蓋 $_GET,$_COOKIE 覆蓋 $_POST。

三、經典實驗:表單 action 帶參數 + 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

結論:

  • URL 查詢字串進入 $_GET
  • 表單字段進入 $_POST
  • $_REQUEST 取後者(POST 覆蓋 GET)
  • 最佳實踐:明確使用 $_GET 或 $_POST,避免 $_REQUEST 帶來的隱性 Bug。

四、安全性深度剖析

1. GET 風險

  • 瀏覽器歷史、伺服器日誌、Referer 標頭、代理伺服器均會記錄完整 URL(含敏感參數)。
  • CSRF 攻擊易構造惡意連結誘導受害者點擊。
  • 長度限制導致大資料截斷。

2. POST 優勢

  • Body 不會出現在日誌/歷史中(除非開發者主動記錄)。
  • 配合 SameSite Cookie、CSRF Token 可有效防禦 CSRF。
  • 支援檔案上傳、JSON、XML 等複雜載荷。

3. $_REQUEST 陷阱

  • 來源模糊:無法區分資料來自 Query、Body 還是 Cookie。
  • Cookie 注入:攻擊者植入同名 Cookie 可覆蓋 POST/GET 值(variables_order 中 C 在 P 後)。
  • 性能損耗:每次請求合併三大陣列。

五、最佳實踐清單

  1. 語義化選擇:查詢/分頁/搜尋 → $_GET;寫入/登入/上傳 → $_POST。
  2. 禁用 $_REQUEST:專案規範中明確禁止,靜態分析工具(PHPStan/Psalm)可配置規則攔截。
  3. 輸入過濾:使用 filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) 等內建過濾器,而非直接 $_GET['id']。
  4. CSRF 保護:所有 POST 表單攜帶 Token,驗證 $_POST['_token'] === $_SESSION['_token']。
  5. 限制請求大小:post_max_size = 8M、upload_max_filesize = 2M 按業務調整。
  6. HTTPS 強制:傳輸層加密防止中間人竄改 GET/POST 資料。

六、特殊場景:action 帶參數 + POST 表單

若業務必須在 action 帶查詢參數(如 /save?type=article),同時 POST 表單提交:

  • 路由參數用 $_GET['type'] 讀取
  • 表單字段用 $_POST['title'] 讀取
  • 絕不混用 $_REQUEST

總結

$_GET、$_POST、$_REQUEST 的區別本質是 HTTP 協議層面的「查詢字串」vs「請求體」vs「混合來源」。堅持「顯式優於隱式」,根據語義選擇 $_GET 或 $_POST,徹底拒絕 $_REQUEST,是寫出安全、可維護 PHP 代碼的基礎功力。

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