前端使用 JavaScript escape() 編碼中文參數傳遞給 PHP 時,PHP 內建 urldecode() 或 base64_decode() 無法正確還原,因為 escape() 產生 %uXXXX 格式(Unicode 代碼點),而非標準 Percent-encoding。本文提供雙向轉換函數,解決跨語言編碼不一致問題。
// JS 端
window.open('product_list.php?p_sort=' + escape('PHP開發資源網'));
// 產生:product_list.php?p_sort=PHP%u5F00%u53D1%u8D44%u6E90%u7F51
// PHP 端直接 urldecode 失敗,得到亂碼
手動解析 %uXXXX 與標準 %XX,並依 Unicode 代碼點重組 UTF-8 位元組,最後視需求轉為目標編碼(如 GB2312)。
function js_unescape($str) {
$ret = '';
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
if ($str[$i] === '%' && $str[$i+1] === 'u') {
$val = hexdec(substr($str, $i+2, 4));
if ($val < 0x7f) {
$ret .= chr($val);
} elseif ($val < 0x800) {
$ret .= chr(0xc0 | ($val >> 6)) . chr(0x80 | ($val & 0x3f));
} else {
$ret .= chr(0xe0 | ($val >> 12))
. chr(0x80 | (($val >> 6) & 0x3f))
. chr(0x80 | ($val & 0x3f));
}
$i += 5;
} elseif ($str[$i] === '%') {
$ret .= urldecode(substr($str, $i, 3));
$i += 2;
} else {
$ret .= $str[$i];
}
}
return $ret;
}
// 使用:先 js_unescape 再 iconv 轉編碼
$decoded = iconv('utf-8', 'gb2312', js_unescape($_REQUEST['p_sort']));
若需在 PHP 產生與 JS escape() 相容的字串(如組 URL 給前端),可用此函數。
function phpescape($str) {
$returnString = '';
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
$ord = ord($str[$i]);
if ($ord >= 127) { // 多位元組字元(假設輸入為 GB2312)
// 取兩個位元組轉 UCS-2 再轉 hex
$tmp = bin2hex(iconv('gb2312', 'ucs-2', substr($str, $i, 2)));
// Windows 小端序可能需調換位序:$tmp = substr($tmp,2,2).substr($tmp,0,2);
$returnString .= '%u' . $tmp;
$i++; // 消耗兩個位元組
} else {
$returnString .= '%' . dechex($ord);
}
}
return $returnString;
}
encodeURIComponent() (JS) + urldecode() (PHP),皆遵循 RFC 3986 標準,無需額外轉換。escape() 已棄用,現代瀏覽器仍支援但不建議新增使用。