在 Web 開發中,若前端使用 JavaScript 的 escape() 對 URL 參數(特別是中文)進行編碼,後端 PHP 直接使用 urldecode() 或 base64_decode() 無法正確還原,會導致亂碼。本文提供完整的雙向轉換函數與編碼原理解析。
前端代碼:
<a href="" onclick="window.open('product_list.php?p_sort='+escape('PHP開發資源網'));">
生成的 URL:
https://127.0.0.1/shop/product_list.php?p_sort=PHP%u5F00%u53D1%u8D44%u6E90%u7F51
%uXXXX 格式為 Unicode 編碼,PHP 原生函數無法識別。
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);
else if ($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 escape() 輸出為 UTF-8 編碼,PHP 內部若為 GB2312/GBK,需額外轉換:
print iconv('utf-8', 'gb2312', js_unescape($_REQUEST['p_sort']));
輸出結果:PHP開發資源網
反向操作,PHP 生成 JS 兼容的 escape 編碼:
function phpescape($str) {
$sublen = strlen($str);
$returnString = '';
for ($i = 0; $i < $sublen; $i++) {
if (ord($str[$i]) >= 127) {
$tmpString = bin2hex(iconv("gb2312", "ucs-2", substr($str, $i, 2)));
// $tmpString = substr($tmpString,2,2).substr($tmpString,0,2); // Windows 可能需開啟
$returnString .= "%u" . $tmpString;
$i++;
} else {
$returnString .= "%" . dechex(ord($str[$i]));
}
}
return $returnString;
}
encodeURIComponent()(JS)搭配 urldecode()(PHP)更現代、標準。escape() 時,使用上述函數。iconv 轉換帶來的效能損耗與錯誤風險。