處理前端傳入的 \uXXXX 格式字串,或需將中文轉為 Unicode 供 JavaScript 使用時,可利用 PHP iconv 搭配 base_convert 實作雙向轉換。本文提供兩個函式 unicode_encode() / unicode_decode(),支援 BMP 平面字元 (U+0000 ~ U+FFFF)。
<?php
/**
* 字串轉 Unicode 逃逸格式 (\uXXXX)
* @param string $str UTF-8 字串
* @return string 如 "中文" => "\u4e2d\u6587"
*/
function unicode_encode($str) {
// UTF-8 -> UCS-2BE (大端序,每字 2 位元組)
$ucs2 = iconv('UTF-8', 'UCS-2BE', $str);
$len = strlen($ucs2);
$result = '';
for ($i = 0; $i < $len; $i += 2) {
$high = ord($ucs2[$i]);
$low = ord($ucs2[$i + 1]);
if ($high === 0 && $low < 128) {
// ASCII 字元直接保留
$result .= chr($low);
} else {
// 組合成 16 進位 4 碼
$hex = str_pad(dechex($high * 256 + $low), 4, '0', STR_PAD_LEFT);
$result .= '\\u' . $hex;
}
}
return $result;
}
/**
* Unicode 逃逸格式還原為 UTF-8 字串
* @param string $str 含 \uXXXX 格式字串
* @return string UTF-8 字串
*/
function unicode_decode($str) {
// 正則比對 \uXXXX 或普通字元
$pattern = '/\\\\u([0-9a-fA-F]{4})|(.)/s';
$result = '';
preg_match_all($pattern, $str, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
if (!empty($m[1])) {
// \uXXXX 格式
$code = hexdec($m[1]);
// UCS-2BE 兩位元組
$char = chr($code >> 8) . chr($code & 0xFF);
$result .= iconv('UCS-2BE', 'UTF-8', $char);
} else {
// 普通字元
$result .= $m[2];
}
}
return $result;
}
// 測試
$original = 'Hello 中文 😀'; // 注意:Emoji 屬於補充平面,UCS-2 不支援
$encoded = unicode_encode($original);
$decoded = unicode_decode($encoded);
echo "原始: $original\n";
echo "編碼: $encoded\n";
echo "解碼: $decoded\n";
// 輸出:
// 原始: Hello 中文 😀
// 編碼: Hello \u4e2d\u6587 \ud83d\ude00 (Emoji 會變成 surrogate pair)
// 解碼: Hello 中文 😀
?>
str_pad 補齊 4 碼。/\\\\u([0-9a-fA-F]{4})|(.)/s:優先捕獲 \uXXXX,否則捕獲任意單一字元 (含換行)。\uD83D\uDE00),解碼時 iconv 會自動合併還原。| 場景 | 本函式支援 | 建議方案 |
|---|---|---|
| 純 BMP 字元 (中日韓、基本符號) | ✅ 完美 | 直接使用 |
| Emoji / 補充平面字元 | ⚠️ 產生 Surrogate Pair | 改用 json_encode($str, JSON_UNESCAPED_UNICODE) 反向處理 |
| 需輸出 JSON 給前端 | ❌ 格式不同 | json_encode($str, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG) |
| 高效能批次處理 | ⚠️ iconv 有開銷 | 考慮 mb_convert_encoding 或 C 擴展 |
// 編碼:利用 json_encode 內建 Unicode 逃逸
function unicode_encode_modern($str) {
return json_encode($str, JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT | JSON_HEX_TAG);
// 注意:json_encode 會包雙引號,需自行 trim
}
// 解碼:利用 json_decode
function unicode_decode_modern($str) {
// 確保字串被雙引號包裹且為有效 JSON 字串字面值
$json = '"' . addcslashes($str, '"\\') . '"';
return json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
}