核心差異一覽
| 特性 | urlencode() | rawurlencode() |
| 標準依據 | application/x-www-form-urlencoded (HTML 表單) | RFC 3986 (URI 標準) |
| 空格編碼 | + (加號) | %20 |
| 保留字元 | -_. 不編碼 | -_.~ 不編碼 (波浪號差異) |
| 適用場景 | POST 表單、URL 查詢字串值 | URL 路徑、Header、OAuth 簽名 |
編碼範圍對照
<?php
$test = "Hello World! @#$/中文";
echo "urlencode: " . urlencode($test) . "\n";
// Hello+World%21+%40%23%24%2F%E4%B8%AD%E6%96%87
echo "rawurlencode: " . rawurlencode($test) . "\n";
// Hello%20World%21%20%40%23%24%2F%E4%B8%AD%E6%96%87
?>
實戰場景選擇指南
場景一:建構 URL 查詢字串(推薦 urlencode)
<?php
$params = [
'q' => 'PHP 教學',
'page' => 2,
'tag' => 'web+dev'
];
$query = http_build_query($params); // 內部使用 urlencode
echo "https://example.com/search?$query";
// https://example.com/search?q=PHP+%E6%95%99%E5%AD%B8&page=2&tag=web%2Bdev
?>
場景二:建構 URL 路徑段落(必須 rawurlencode)
<?php
$username = "john doe";
$path = "/user/" . rawurlencode($username) . "/profile";
// /user/john%20doe/profile
?>
場景三:OAuth 1.0 簽名基礎字串(強制 rawurlencode)
<?php
function oauth_encode($str) {
return str_replace('%7E', '~', rawurlencode($str)); // RFC 5849 要求 ~ 不編碼
}
$base = "GET&" . oauth_encode("https://api.example.com/resource") . "&" .
oauth_encode("oauth_consumer_key=key&oauth_nonce=123");
// 簽名計算...
?>
場景四:JavaScript 互通(前端 encodeURIComponent = rawurlencode)
<?php
// PHP 接收 JS 傳來的參數
$js_encoded = $_GET['data']; // JS: encodeURIComponent("中文") -> "%E4%B8%AD%E6%96%87"
$decoded = rawurldecode($js_encoded); // 正確解碼
// 若用 urldecode() 會將 %20 解為空格,但 + 會解為空格,導致實際 + 字元遺失
?>
解碼函數對應
| 編碼函數 | 解碼函數 | 空格處理 |
| urlencode() | urldecode() | + → 空格 |
| rawurlencode() | rawurldecode() | %20 → 空格,+ 保持 + |
常見錯誤與修正
- 錯誤:
urlencode($path_segment) → 空格變 +,伺服器解析為查詢字串分隔符
- 錯誤:雙重編碼
urlencode(urlencode($str))
- 修正:路徑用
rawurlencode,查詢值用 urlencode,整體 URL 用 http_build_query 組裝
遷移建議
新專案優先使用 rawurlencode,除非明確處理 application/x-www-form-urlencoded 表單資料。PSR-7 UriInterface 實作內部皆採 RFC 3986。