应避免使用 $_REQUEST,因其混用 GET、POST、COOKIE 导致来源不明、覆盖风险与安全漏洞;必须明确使用 $_GET 或 $_POST,并通过手动合并(如 $_POST['x'] ?? $_GET['x'])控制优先级。

$_REQUEST 会混掉 POST 和 GET 参数,导致逻辑错乱
它把 $_GET、$_POST、$_COOKIE 全部合并,同名键值会被后加载的覆盖。比如 URL 带 ?id=1,表单又提交 id=2,$_REQUEST['id'] 取到的是 2——但你根本不知道这个 2 是来自表单还是被恶意构造的 Cookie。
常见错误现象:
– 管理后台“删除 ID=1 的记录”,结果因 URL 里有 ?id=1 被绕过校验,实际删了 $_REQUEST['id'](可能来自伪造的 POST);
– 开启 register_globals 旧配置时更危险,但即使关了,$_REQUEST 仍自带不确定性。
- 明确要读 URL 参数?只用
$_GET - 明确是表单提交?只用
$_POST - 需要同时处理两种来源?手动合并,比如
$id = $_POST['id'] ?? $_GET['id'] ?? null,并加注释说明意图 - 别依赖
$_REQUEST做权限判断或关键业务分支
$_REQUEST 在 PHP 配置中可被禁用,但默认开启
PHP 的 request_order 配置项决定哪些超全局变量参与合并,默认是 "GP"(GET + POST),所以 $_COOKIE 不进 $_REQUEST ——但很多老项目还开着 variables_order = "EGPCS",这就让 Cookie 也混进来了。
检查方式:
– 运行 phpinfo() 查 request_order 和 variables_order;
– 或直接打印 ini_get('request_order')。
立即学习“PHP免费学习笔记(深入)”;
- 线上环境建议设为
"GP",彻底排除 Cookie 干扰 - 更稳妥的做法是在
php.ini中设request_order = ""(空字符串),这样$_REQUEST变成空数组,强制开发者显式选择来源 - 注意:Apache 的
.htaccess或 Nginx 的fastcgi_param无法修改该配置,必须改 PHP 层
替代方案比 $_REQUEST 更清晰,也更容易测
单元测试里模拟请求时,$_REQUEST 让输入来源模糊,mock 成本高;而只依赖 $_GET 或 $_POST,输入边界一目了然。
示例对比:
– 危险写法:if ($_REQUEST['action'] === 'delete') { ... }
– 安全写法:if ($_POST['action'] ?? '' === 'delete') { ... }
- 框架如 Laravel、Symfony 根本不暴露
$_REQUEST,统一走 Request 对象,来源明确 - 自建轻量路由时,可用封装函数:
get_input('id', 'post')或get_input('token', 'get'),内部做类型校验和过滤 - 如果真要“优先 POST 再 fallback GET”,写成
$_POST['x'] ?? $_GET['x'] ?? null,语义和执行顺序都可控
$_REQUEST 在调试时有用,但绝不该进生产逻辑
开发阶段临时 var_dump($_REQUEST) 看整体输入没问题,但上线前必须删掉或替换。它的存在本身就在鼓励“偷懒式编程”——用一个变量掩盖对数据来源的思考。
容易被忽略的一点:
PHP 8.0+ 对未定义索引的 $_REQUEST 访问会触发 Notice(和 $_GET/$_POST 一样),但它不会帮你指出“你本该查的是 POST 而不是 REQUEST”。
- IDE 和静态分析工具(如 PHPStan)对
$_REQUEST的类型推断基本失效,没法提示缺失字段 - 代码审查时,看到
$_REQUEST应直接标为待修复项,除非上下文明确说明“此处故意兼容多入口” - 最麻烦的情况:遗留系统里
$_REQUEST已遍布各处,建议先加日志统计高频 key,再分批替换,别指望一次清完



















