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

解析 PHP 中的 escape 函數與 JS 編碼對應關係

     編輯:PHP 綜合知識

JavaScript escape 編碼格式深度解析與 PHP 反解實作

JS escape() 生成 %uXXXX 格式,PHP urldecode() 無法處理。本文詳細解析編碼原理,提供多種 PHP 反解方案,並補充編碼範圍與正則應用知識。

問題場景

// 前端
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

// 後端 PHP
urldecode($_GET['p_sort']); // 無效,返回原字串
base64_decode($_GET['p_sort']); // 無效

核心反解函數 js_unescape()

<?php
function js_unescape($str) {
    $ret = '';
    $len = strlen($str);
    for ($i = 0; $i < $len; $i++) {
        if ($str[$i] == '%' && $str[$i+1] == 'u') { // %uXXXX
            $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] == '%') { // %XX
            $ret .= urldecode(substr($str, $i, 3));
            $i += 2;
        } else {
            $ret .= $str[$i];
        }
    }
    return $ret;
}

// 使用 (注意編碼轉換)
$decoded = js_unescape($_REQUEST['p_sort']); // UTF-8
echo iconv('UTF-8', 'GB2312', $decoded);     // 轉為 GB2312 輸出

PHP 實現 escape 編碼 (多種寫法)

寫法一:逐字符處理

function phpescape($str) {
    $sublen = strlen($str);
    $returnString = "";
    for ($i = 0; $i < $sublen; $i++) {
        if (ord($str[$i]) >= 127) { // 非 ASCII
            $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;
}

寫法二:正則分組處理 (推薦)

function phpEscape($str) {
    preg_match_all("/[\x80-\xff].|[\x01-\x7f]+/", $str, $r);
    $ar = $r[0];
    foreach ($ar as $k => $v) {
        if (ord($v[0]) < 128) { // ASCII 字符串
            $ar[$k] = rawurlencode($v);
        } else { // 中文字符 (雙位元組)
            $ar[$k] = "%u" . bin2hex(iconv("GB2312", "UCS-2", $v));
        }
    }
    return join("", $ar);
}

正則原理解析

  • [\x80-\xff].:匹配雙位元組字符 (首位元組 0x80-0xFF + 任意第二位元組) → 中文
  • [\x01-\x7f]+:匹配連續單位元組字符 (0x01-0x7F) → ASCII 字串
  • 分組後分別處理:ASCII 用 rawurlencode,中文轉 UCS-2 後 bin2hex

另一種解碼實作 (支援多種格式)

function unescape($str) {
    $str = rawurldecode($str);
    preg_match_all("/%u.{4}|&#x.{4};|&#\d+;|.+/U", $str, $r);
    $ar = $r[0];
    foreach ($ar as $k => $v) {
        if (substr($v, 0, 2) == "%u") {
            $ar[$k] = iconv("UCS-2", "GBK", pack("H4", substr($v, -4)));
        } elseif (substr($v, 0, 3) == "&#x") {
            $ar[$k] = iconv("UCS-2", "GBK", pack("H4", substr($v, 3, -1)));
        } elseif (substr($v, 0, 2) == "&#") {
            $ar[$k] = iconv("UCS-2", "GBK", pack("n", substr($v, 2, -1)));
        }
    }
    return join("", $ar);
}

編碼範圍速查表

編碼範圍說明
GBK\x00-\xff雙位元組完整範圍
\x20-\x7fASCII 可見字符
\xa1-\xff中文區
\x80-\xff中文區 (含擴展)
UTF-8/Unicode\u4e00-\u9fa5中文 CJK 統一表意文字
\x3130-\x318F韓文字母
\xAC00-\xD7A3韓文音節
\u0800-\u4e00日文區塊

正則應用範例

<?php
// 移除中文 (GBK)
$str = preg_replace("/([\x80-\xff])/", "", $str);
// 移除中文 (UTF-8)
$str = preg_replace("/([\x{4e00}-\x{9fa5}])/u", "", $str);
// 提取中文
preg_match_all("/[\x{4e00}-\x{9fa5}]+/u", $str, $match);

理解編碼本質與位元組結構,才能編寫正確、高效的編解碼邏輯。

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