$_get、$_post、$_request 来源和行为迥异:$_get 读 url 参数,$_post 读表单或请求体数据,$_request 是两者的合并(可能含 $_cookie),但结果依赖 request_order 配置,同名参数易被覆盖;三者中仅 $_request 可写且修改影响后续读取;api 应用 $_get 或 php://input 读 json,禁用 $_request。

$_GET、$_POST、$_REQUEST 这三个最常用,但行为差异很大
它们都存用户传入的数据,但来源和触发时机完全不同:$_GET 只读 URL 查询参数,$_POST 只读表单 POST 数据(或 API 请求体),$_REQUEST 是前两者的合并——但它还可能包含 $_COOKIE,具体取决于 request_order 配置,默认是 GP(只含 GET 和 POST),但有些老环境设成 GPC,容易导致意外覆盖。
- 永远别直接信任
$_REQUEST,尤其在有同名参数时(比如 URL 带?id=1,表单又提交id=2),结果取决于配置顺序 -
$_GET和$_POST是只读副本,修改它们不影响原始输入;但$_REQUEST修改后,后续读取会变,且不反映真实请求源 - API 接口务必用
$_GET或file_get_contents('php://input')读 JSON,别碰$_REQUEST
$_SERVER 包含运行时上下文,但字段兼容性差
$_SERVER 看起来全平台一致,其实大量键名依赖 SAPI 类型(CLI / Apache / FPM)和 Web 服务器配置。比如 $_SERVER['REQUEST_URI'] 在 CLI 下不存在,$_SERVER['HTTP_X_FORWARDED_FOR'] 完全由客户端或代理注入,不可信。
-
$_SERVER['SCRIPT_NAME']和$_SERVER['PHP_SELF']都可能被恶意构造的 URL 注入路径遍历或 XSS,输出前必须过滤 -
$_SERVER['REMOTE_ADDR']在 Nginx + PHP-FPM 架构下常被反向代理覆盖,需配合real_ip_header和set_real_ip_from才能拿到真实 IP - 判断是否 HTTPS 不要只看
$_SERVER['HTTPS'] === 'on',有些负载均衡器只设$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'
$_SESSION 和 $_COOKIE 必须主动启用才能用
这两个不是“自动就存在”的变量。PHP 默认关闭会话机制,$_SESSION 在没调用 session_start() 前是空数组,且后续任何输出(包括空格、BOM)都会导致启动失败;$_COOKIE 虽然无需手动开启,但值是 HTTP 请求头里原始字符串,未经解码、未验证、未过滤。
-
session_start()必须在任何输出之前调用,否则报错headers already sent;CLI 模式下也能用,但无意义 -
$_COOKIE中的值不会自动urldecode(),如果前端用encodeURIComponent传了中文,这里还是编码后的字符串 - 不要把敏感数据(如用户 ID、权限)直接塞进
$_COOKIE,更别用它替代$_SESSION存登录态——cookie 可被篡改,session_id 才是关键
其他预定义变量基本已淘汰,别在新项目里用
$GLOBALS、$_ENV、$php_errormsg、$http_response_header 这些要么功能重叠,要么行为不稳定,要么已被弃用。PHP 8.1 起 $php_errormsg 彻底移除,$_ENV 默认为空,除非显式调用 putenv() 或配置 variables_order。
立即学习“PHP免费学习笔记(深入)”;
-
$GLOBALS是所有全局变量的引用数组,但直接读写$_POST比写$GLOBALS['_POST']清晰得多,毫无必要绕路 -
$_ENV不等于系统环境变量,它只包含 PHP 启动时导入的部分,Docker 或 systemd 启动的 PHP-FPM 常为空,应改用getenv('DB_HOST') -
$argc和$argv只在 CLI 模式有效,Web 环境下不存在,别在入口脚本里无条件访问它们











