根本原因是url编码不一致与服务端未正确解码,需统一utf-8编码、确保php文件为utf-8无bom、响应头声明charset,并优先通过$_server['query_string']手动解析。

PHP 获取带中文的 GET 参数时乱码,根本原因是 URL 编码不一致 + 服务端未正确解码,不是 PHP 本身的问题,而是浏览器、HTTP 协议和 PHP 配置协同失配的结果。
浏览器发的是 UTF-8 编码的 %E4%B8%AD%E6%96%87,但 $_GET 自动解码后却当 ISO-8859-1 处理
现代浏览器(Chrome/Firefox/Safari)对地址栏中手动输入的中文,会自动用 UTF-8 编码再百分号编码(如 中 → %E4%B8%AD)。但 PHP 的 $_GET 在填充前默认调用 urldecode(),而该函数不指定字符集,底层按字节流处理——如果 PHP 运行环境 locale 或内部编码不是 UTF-8,就容易把多字节序列拆开解读,显示成 或乱码。
- 检查你是否在 URL 中直接写了中文(如
?name=张三),这种写法依赖浏览器自动编码,不可靠;应改用encodeURIComponent('张三')前端编码 - 不要依赖
iconv()或mb_convert_encoding()对$_GET['name']二次转码——它很可能已经是损坏过的字符串,越转越错 - 确认 Web 服务器(Apache/Nginx)没做额外的 URL 重写或解码干预,比如 Apache 的
mod_rewrite中用了[B]标志但后端又重复解码
PHP 文件自身编码必须是 UTF-8 无 BOM,且响应头声明 Content-Type
即使 GET 参数解码正确,如果 PHP 文件保存为 GBK 或带 BOM 的 UTF-8,PHP 解析源码时可能出错;更常见的是输出 HTML 时没声明编码,导致浏览器用错误编码渲染表单或链接中的中文。
- 用编辑器(如 VS Code、Notepad++)确认 PHP 文件编码是
UTF-8 without BOM,不是UTF-8 with BOM - 在输出 HTML 前加
header('Content-Type: text/html; charset=utf-8');,或在 HTML 中确保有<meta charset="utf-8"> - 避免在 PHP 文件开头有任何空格、UTF-8 BOM 字节或 echo/print 语句,否则 header 会发送失败
最稳的接收方式:绕过 $_GET,用 parse_str() + urldecode() 手动解析原始 QUERY_STRING
当 Nginx 或某些 CGI 环境下 $_GET 行为异常(比如被多次解码),直接读取原始查询字符串并手动处理,能完全掌控解码逻辑。
立即学习“PHP免费学习笔记(深入)”;
if (isset($_SERVER['QUERY_STRING'])) {
$raw_query = $_SERVER['QUERY_STRING'];
// 先还原原始字节,再用 UTF-8 解释
parse_str(urldecode($raw_query), $parsed);
$name = $parsed['name'] ?? '';
}
-
urldecode()是字节安全的,不会像$_GET那样受 php.ini 中default_charset影响 - 此方法不依赖
mbstring扩展,兼容 PHP 5.4+ 所有环境 - 注意:如果前端用了
encodeURI()(只编码非 ASCII,不编码/ ? & =),就不能直接urldecode(),得先str_replace()恢复特殊符号再解码
真正麻烦的从来不是“怎么让中文显示出来”,而是「哪一层在什么时候做了什么编码操作」——浏览器、Nginx rewrite、PHP 的 auto_globals_jit、甚至 CDN 的 query string 处理,都可能悄悄改写原始字节。盯住 $_SERVER['QUERY_STRING'] 的原始值,比调试 $_GET 快得多。











