rawurlencode必须用于url路径段编码,因其按rfc3986将空格转%20、保留/和~,而urlencode将空格转+且编码/,易致400错误或路由失败;解码须严格配对。

rawurlencode 和 urlencode 看起来只差一个词,但用错地方会直接导致 API 调不通、路径 400、中文变乱码——根本原因不是 PHP 有问题,而是你把 URL 的不同段当成了同一类东西来处理。
空格编码不同:+ vs %20 是最常翻车的点
这是两者最直观、也最致命的差异:
-
urlencode('hello world')→hello+world -
rawurlencode('hello world')→hello%20world
HTTP 协议本身(RFC 3986)规定空格必须是 %20;+ 只在 application/x-www-form-urlencoded 这种表单提交场景里被约定俗成地接受。现代 Web 服务器(Nginx/Apache)默认按 RFC 解析 URI,遇到 path 段里的 + 或未编码中文,直接返回 400 Bad Request。
典型错误:前端用 encodeURIComponent('张三') 发请求(等价于 PHP 的 rawurlencode),后端却用 urldecode($_GET['name']) 接收——urldecode 会把 + 当空格,但这里根本没 +,结果解出来是乱码或截断。
斜杠 / 和波浪 ~ 的处理完全相反
URL 的结构分段(scheme、host、path、query)对哪些字符该编码有明确要求:/ 在 path 中是分隔符,不能编码;~ 是保留字符,按 RFC 不应编码。
-
urlencode('/api/v1')→%2Fapi%2Fv1(把斜杠也编码了,path 彻底失效) -
rawurlencode('/api/v1')→/api/v1(保持结构,符合规范) -
urlencode('file~temp')→file%7Etemp(~被编码) -
rawurlencode('file~temp')→file~temp(~保留原样)
如果你在拼 RESTful 路径如 /user/张三 或生成下载链接 /download/报告.pdf,必须用 rawurlencode 处理其中的非 ASCII 部分,否则 Nginx 日志里能看到清晰的 400 记录。
什么时候必须用 rawurlencode?
只要涉及「URL 结构本身」,而不是「表单提交体」,就该无条件选 rawurlencode:
- 拼接路径段(path):比如
/api/user/.rawurlencode($id) - 构造带中文的跳转地址:
header('Location: /search?q=' . rawurlencode($q)) - 生成签名原文(如微信、支付宝回调验签):签名前的原始参数字符串必须严格按 RFC 编码,否则哈希值对不上
- 手动构造 cURL 请求的 URL(非
-d参数体):如curl_setopt($ch, CURLOPT_URL, $base . '?' . http_build_query($params))中的$base若含动态 path,需提前rawurlencode
唯一可考虑 urlencode 的场景:你正在手写 application/x-www-form-urlencoded 格式的 POST body,且对方接口明确要求空格传 +(极少见,多为老旧内部系统)。
解码必须配对,$_SERVER['REQUEST_URI'] 是个例外
PHP 自动对 $_GET 和 $_POST 做了一次 urldecode(兼容 + 和 %xx),所以通常不用再解;但 $_SERVER['REQUEST_URI'] 是原始未处理字符串,含 %20 和中文编码,必须用 rawurldecode 才能还原。
错误示范:rawurldecode($_GET['q']) —— $_GET['q'] 已被自动解过一次,再用 rawurldecode 会导致二次解码,%2520 这类嵌套编码就出来了。
记住这个铁律:rawurlencode 编的,只能用 rawurldecode 解;urlencode 编的,才用 urldecode。混用等于主动制造乱码。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











