应先用isset()或array_key_exists()判断键是否存在,再对输出到html的值用htmlspecialchars()转义,数字类型须用filter_input()验证,特殊字符参数需手动解析query_string。

怎么安全读取 $_GET 里的值
直接用 $_GET['id'] 可能报 Notice 或导致 XSS,不是所有参数都存在,也不是所有值都可信。$_GET 是超全局数组,但 PHP 不会自动过滤或校验内容。
实操建议:
- 永远用
isset()或array_key_exists()判断键是否存在,再读取,避免未定义索引警告 - 对输出到 HTML 的值,必须用
htmlspecialchars()转义,比如echo htmlspecialchars($_GET['q'] ?? '', ENT_QUOTES, 'UTF-8'); - 需要数字类型时,别信
(int)强转——它会把"123abc"变成123,应改用filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT) - 空字符串、
"0"、"false"都是合法的 GET 值,不能靠empty()粗暴判断是否“有值”
parse_url() + parse_str() 手动解析当前 URL 参数
当你要处理重写后的 URL(如 /user/123)或想绕过 $_GET 的局限(比如参数名含点、中括号),就得自己拆 URL。
常见错误现象:直接对 $_SERVER['REQUEST_URI'] 用 parse_str(),结果漏掉协议、host,还可能混入路径部分。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 先用
parse_url($_SERVER['REQUEST_URI'])提取query部分,再传给parse_str() - 注意
parse_str()默认会覆盖已有变量,务必传第二个参数接收结果,例如:parse_str($query, $output); - 如果 URL 含编码(如
%20),parse_str()会自动解码;但若原始参数本身就是双重编码,得先urldecode()一次
为什么 $_SERVER['QUERY_STRING'] 比 $_GET 更可靠
$_GET 是 PHP 根据 QUERY_STRING 自动解析并做了一些默认处理(比如自动解码、丢弃重复键),而 $_SERVER['QUERY_STRING'] 是原始字符串,一字不差。
使用场景:
- 要保留原始参数顺序或重复键(如
?tag=a&tag=b),$_GET只留最后一个,QUERY_STRING全在 - 调试时比对 Nginx/Apache 实际收到的请求,避免被 PHP 配置(如
arg_separator.input)干扰 - 某些框架或路由层会清空
$_GET,但QUERY_STRING不受影响
性能影响几乎为零,兼容性从 PHP 4 到 8.x 都一致。
GET 参数里有特殊字符(点、中括号、空格)怎么办
PHP 默认把 user.name 解析成 $_GET['user_name'],把 arr[0] 当成数组自动展开——这常导致参数名失真或意外覆盖。
原因在于 PHP 的 variables_order 和 arg_separator.input 配置,且无法在运行时修改。
实操建议:
- 前端发请求时,用
encodeURIComponent编码所有参数名和值,后端仍需手动解析 - 服务端改用
file_get_contents('php://input')不行(GET 没 body),只能回到parse_url() + parse_str()方案 - 若必须支持点号参数,可在 Nginx 中加
underscores_in_headers on;并改用 header 传参,但这已脱离 GET 范畴
最麻烦的其实是参数名动态拼接(比如 field_{$id})+ 特殊字符混合,这时候别硬塞进 $_GET,老实用原始 query 字符串切片或正则提取更稳。











