结论:查询参数值必须单独用urlencode()编码,不可拼接未编码中文或特殊字符,否则+被误作空格、/截断路径、中文乱码;因浏览器和php依赖标准编码解析$_get,未编码会导致解析错乱。

直接说结论:对 URL 查询参数的每个值单独调用 urlencode(),不要编码整个 URL,也不要跳过中文或空格 —— 否则 + 会被当成空格、/ 会截断路径、中文会乱码。
为什么不能直接拼接中文或特殊字符到 URL 里
浏览器和 PHP 对 $_GET 的解析依赖于标准编码格式。如果传 ?q=你好+world,PHP 会把 + 当成空格解码,得到 "你好 world";如果传 ?path=a/b/c,/ 可能被 Web 服务器当作路径分隔符提前截断,导致 $_GET['path'] 只拿到 a。
常见错误现象:
- 中文显示为
%E4%B8%AD%E6%96%87却没被自动还原 → 实际是没编码就拼进 URL,或编码了但接收端误用了urldecode() -
header("Location: ?q=$str")重定向后$_GET['q']缺失或错乱 → 没对$str调用urlencode() - 数学表达式
a+b/c变成a b/c→+未编码,被当空格处理
urlencode() 的实际调用方式
它只处理字符串值,不碰键名、不碰 ? & = 这些结构字符。正确姿势是「先取值、再编码、最后拼」。
使用场景示例:
- 构造搜索链接:
$url = "search.php?q=" . urlencode($keyword) . "&page=" . urlencode($page) - 重定向带用户输入:
header("Location: result.php?msg=" . urlencode($_POST['msg'])); exit; - API 请求参数:
$api_url = "https://api.example.com/v1?token=" . urlencode($token) . "&data=" . urlencode($json_str)
注意:urlencode() 默认按字节处理,所以必须确保输入字符串是 UTF-8 编码。如果源数据来自 GBK 或数据库旧编码,得先转码:urlencode(mb_convert_encoding($str, 'UTF-8', 'GBK'))。
urlencode 和 rawurlencode 的关键区别
两者都编码非字母数字字符,但空格和保留字符(/ ? :)的处理不同:
-
urlencode("a b/c")→a+b%2Fc(空格变+,/变%2F) -
rawurlencode("a b/c")→a%20b%2Fc(空格变%20,/也变%2F)
选哪个?
- 用于查询参数(
?key=value&...)→ 用urlencode(),它匹配 PHP 自动解码$_GET的行为 - 用于 URL 路径段(如
/user/张三/profile)→ 用rawurlencode(),避免+引发歧义,更贴近 RFC 3986
别混用:用 urlencode() 编码的值,PHP 接收时自动解码;用 rawurlencode() 编码的,若要手动还原,得配 rawurldecode(),否则 %20 不会被 urldecode() 正确处理。
最容易被忽略的三个细节
一是 urlencode() 不会递归处理数组,想编码整个数组请用 http_build_query();二是它不验证输入合法性,传 null 或资源类型会警告,务必过滤;三是编码后的字符串不能再被 urlencode() 套一层,否则 % 变成 %25,彻底无法还原。
真正麻烦的从来不是函数怎么写,而是哪一步该编码、哪一步不该碰、以及谁负责解码 —— PHP 在 $_GET 层已默默做了,你只需守住「只编码值」这一条线。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











