核心差異一覽
| 字符 | urlencode | rawurlencode | RFC |
| 空格 | + (加號) | %20 | RFC 3986 推薦 %20 |
| ~ | %7E | ~ (保留) | RFC 3986 不編碼 |
| 其他 | 同 rawurlencode | 字母數字、-_. 不編碼,其餘 %XX | |
代碼驗證
<?php
$str = "hello world";
echo urlencode($str) . "\n"; // hello+world
echo rawurlencode($str) . "\n"; // hello%20world
// 完整可打印 ASCII 對比
for ($i=0x20; $i<0x7f; $i++) $ascii .= chr($i);
echo "urlencode: " . preg_replace('/%.{2}/','',urlencode($ascii)) . "\n"; // +-.
echo "rawurlencode: " . preg_replace('/%.{2}/','',rawurlencode($ascii)) . "\n"; // -._
// urlencode 多編碼 '+',少保留 '~'
?>
為什麼這很重要?
- URL 路徑/查詢值:空格必須為
%20,+ 會被某些服務器/框架誤解析為空格或保留字符,導致參數丟失或簽名驗證失敗。
- HTTP 傳輸:
application/x-www-form-urlencoded 規範規定空格為 +,故表單提交用 urlencode;但構建 URL 字符串時應用 rawurlencode。
- 互操作性:Java
URLEncoder.encode 默認空格編為 +,需手動 replace("+", "%20");Python urllib.parse.quote 默認 %20(相當於 rawurlencode)。
JavaScript 對照
| 函數 | 空格 | 編碼集 | 適用場景 |
escape() (已棄用) | %20 | Unicode %uXXXX | 不推薦 |
encodeURI() | %20 | 保留 ;,/?:@&=+$# 等 | 整個 URL |
encodeURIComponent() | %20 | 最全面,僅保留 -_.~!*'() | 查詢參數值、POST body |
const val = "用戶名&密碼";
console.log(encodeURIComponent(val)); // "%E7%94%A8%E6%88%B7%E5%90%8D%26%E5%AF%86%E7%A0%81"
// PHP 端接收:urldecode($_GET['val']) 正確還原
最佳實踐速查
- 構建 URL 查詢字符串:
http_build_query($arr, '', '&', PHP_QUERY_RFC3986)(PHP 5.4+)自動使用 rawurlencode。
- 手動拼接參數值:
rawurlencode($value)。
- 解析傳入參數:PHP 自動
urldecode 填充 $_GET/$_POST/$_REQUEST,無需手動解碼。
- Java 互通:
URLEncoder.encode(s, "UTF-8").replace("+", "%20")。
- 避免雙重編碼:已編碼字符串勿再次傳入 encode 函數。
總結
構建 URL 時請始終使用 rawurlencode / http_build_query(..., PHP_QUERY_RFC3986) / JS encodeURIComponent,確保空格編為 %20,符合 RFC 3986,避免跨語言、跨框架解析錯誤。urlencode 僅用於模擬瀏覽器表單提交(Content-Type: application/x-www-form-urlencoded)的 body 組裝。