首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

JS escape 與 PHP URL 編碼互轉完整指南:解決中文參數亂碼

     編輯:PHP 相關知識

前後端分離架構下,JavaScript 的 escape()、encodeURIComponent() 與 PHP 的 urldecode()、rawurldecode() 編碼規則不一致,常導致中文參數在傳遞過程中產生亂碼或解碼失敗。本文系統梳理編碼差異,提供可直接落地的互轉函式庫。

編碼函式對照表

環境函式編碼規則適用場景
JSescape()ASCII 字元不編碼;非 ASCII 轉 %uXXXX (Unicode) 或 %XX (Latin-1)已棄用,舊專案維護
JSencodeURI()保留 URL 結構字元 (;/?:@&=+$,#),其餘 UTF-8 編碼為 %XX整個 URL 編碼
JSencodeURIComponent()所有非保留字元 UTF-8 編碼為 %XX推薦:查詢參數值編碼
PHPurlencode()空格轉 +,其他同 RFC 3986表單提交、查詢字串
PHPrawurlencode()空格轉 %20,嚴格遵循 RFC 3986推薦:REST API、路徑片段

核心問題:escape() 產生的 %uXXXX PHP 無法原生解碼

當前端使用 escape('中文') 產生 %u4E2D%u6587 時,PHP 的 urldecode() 會原樣輸出,因為它不識別 %u 前綴。需自行實作解碼器:

<?php
/**
 * 解碼 JavaScript escape() 產生的字串
 * @param string $str 含 %uXXXX 或 %XX 格式的字串
 * @return string UTF-8 解碼後的字串
 */
function js_unescape($str) {
    $ret = '';
    $len = strlen($str);
    for ($i = 0; $i < $len; $i++) {
        if ($str[$i] === '%' && isset($str[$i+1]) && $str[$i+1] === 'u') {
            // Unicode 格式 %uXXXX
            $val = hexdec(substr($str, $i+2, 4));
            $ret .= _utf8_encode_char($val);
            $i += 5;
        } elseif ($str[$i] === '%' && isset($str[$i+2])) {
            // 標準 %XX 格式
            $ret .= urldecode(substr($str, $i, 3));
            $i += 2;
        } else {
            $ret .= $str[$i];
        }
    }
    return $ret;
}

function _utf8_encode_char($cp) {
    if ($cp < 0x80) return chr($cp);
    if ($cp < 0x800) return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
    if ($cp < 0x10000) return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
    // 補充平面字元(Emoji 等)
    return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
}
?>

完整流程示範

<?php
// 前端傳遞:escape('PHP開發資源網') → %u5F00%u53D1%u8D44%u6E90%u7F51
$raw = $_GET['p_sort']; // 取得原始編碼字串
$utf8 = js_unescape($raw); // 解碼為 UTF-8

// 若專案內部編碼為 GBK/Big5,需額外轉碼
$final = iconv('UTF-8', 'GBK//IGNORE', $utf8);
echo $final; // 正確顯示:PHP開發資源網
?>

反向操作:PHP 產生相容 escape() 的編碼

若需在 PHP 端產生給舊版 JS 使用的編碼:

<?php
function php_escape($str, $input_charset = 'GBK') {
    $str = iconv($input_charset, 'UCS-2BE', $str); // 轉為 UCS-2 大端序
    $out = '';
    for ($i = 0; $i < strlen($str); $i += 2) {
        $char = substr($str, $i, 2);
        $val = unpack('n', $char)[1];
        if ($val < 128 && !in_array($val, [37, 64, 35, 43, 38, 61, 59, 58, 44, 36])) {
            $out .= chr($val); // ASCII 保留字元不編碼
        } else {
            $out .= sprintf('%%u%04X', $val);
        }
    }
    return $out;
}
?>

最佳實踐建議

  1. 棄用 escape():現代專案全端統一使用 encodeURIComponent() / rawurlencode(),編碼規則一致,無需轉換層。
  2. 指定字元集:所有 iconv、mb_convert_encoding 呼叫必須明確宣告來源/目標編碼,避免隱性轉換導致資料損毀。
  3. 單元測試覆蓋:針對 ASCII、中文、Emoji、特殊符號(%、&、=、+、空格)建立測試向量,確保雙向轉換無損。

掌握編碼細節,才能在中文參數傳遞中徹底杜絕亂碼困擾。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved