前端傳輸、API 交互、數據庫存儲中常需將中文轉為 Unicode 轉義序列(如 `\u4e2d\u6587` 或 `中`)。PHP 無原生單函數支持,本文提供兩種方案:手動位運算法(可控、無依賴)與 JSON 函數法(極簡、現代項目首選)。
<?php
/**
* 字符串轉 Unicode 轉義 (\uXXXX 格式)
* @param string $str UTF-8 字符串
* @return string 轉義後字符串
*/
function unicode_encode($str) {
$str = iconv('UTF-8', 'UCS-2BE', $str); // 轉為 UCS-2 大端序(每字符 2 字節)
$len = strlen($str);
$out = '';
for ($i = 0; $i < $len; $i += 2) {
$high = ord($str[$i]);
$low = ord($str[$i+1]);
if ($high > 0) { // 非 ASCII(雙字節)
$out .= '\u' . str_pad(dechex($high << 8 | $low), 4, '0', STR_PAD_LEFT);
} else { // ASCII 單字節
$out .= chr($low);
}
}
return $out;
}
/**
* Unicode 轉義 (\uXXXX / XXXX;) 解碼為 UTF-8
* @param string $str 包含 \uXXXX 或 XXXX; 的字符串
* @return string 解碼後 UTF-8 字符串
*/
function unicode_decode($str) {
// 匹配 \uXXXX 或 XXXX; 或 DDDD;
$pattern = '/\\\\u([0-9a-fA-F]{4})|([0-9a-fA-F]{4});|(\\d+);/';
return preg_replace_callback($pattern, function($m) {
if (!empty($m[1])) { // \uXXXX
$cp = hexdec($m[1]);
} elseif (!empty($m[2])) { // XXXX;
$cp = hexdec($m[2]);
} else { // DDDD;
$cp = intval($m[3]);
}
// 碼點轉 UTF-8
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);
return chr(0xF0 | $cp >> 18) . chr(0x80 | $cp >> 12 & 0x3F) . chr(0x80 | $cp >> 6 & 0x3F) . chr(0x80 | $cp & 0x3F);
}, $str);
}
// 測試
$original = '中文測試123';
$encoded = unicode_encode($original); // \u4e2d\u6587\u6d4b\u8bd5123
$decoded = unicode_decode($encoded);
var_dump($original, $encoded, $decoded, $original === $decoded); // true
?>
<?php
/**
* 利用 JSON 編碼特性:json_encode 會將 Unicode 字符轉為 \uXXXX
* @param string $str UTF-8 字符串
* @return string \uXXXX 格式字符串
*/
function to_unicode($str) {
// json_encode 要求 UTF-8,輸出帶雙引號,去首尾引號
$json = json_encode($str, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
// JSON_UNESCAPED_UNICODE 會保留中文不轉義,故需去掉該標誌
$json = json_encode($str); // 默認轉義 Unicode
return substr($json, 1, -1); // 去除首尾雙引號
}
/**
* 解碼 \uXXXX 字符串
* @param string $uni \uXXXX 格式字符串
* @return string UTF-8 字符串
*/
function from_unicode($uni) {
// 構造合法 JSON 字符串解析
$json = '"' . $uni . '"';
$decoded = json_decode($json);
return $decoded !== null ? $decoded : $uni; // 解析失敗返回原值
}
// 測試
$str = '中文測試';
$u = to_unicode($str); // \u4e2d\u6587\u6d4b\u8bd5
$d = from_unicode($u); // 中文測試
var_dump($u, $d, $str === $d); // true
?>
| 維度 | 手動位運算法 | JSON 函數法 |
|---|---|---|
| PHP 版本要求 | ≥ 4.0 (iconv) | ≥ 5.2 (json) |
| 代碼量 | ~30 行 | ~5 行 |
| 性能 | 中等 (循環+iconv) | 極快 (C 底層) |
| 輸出格式控制 | 完全可控 (\uXXXX / / 自定義) | 固定 \uXXXX |
| 補字符支持 (Emoji 😀 U+1F600) | 需自行擴展 4 字節邏輯 | 原生支持 (PHP 7+) |
| 適用場景 | 老項目、特殊格式需求、教學 | 現代項目 (PHP 5.4+)、標準 \uXXXX |
<?php
class Unicode {
public static function encode(string $str): string {
return substr(json_encode($str), 1, -1);
}
public static function decode(string $uni): string {
$decoded = json_decode('"' . $uni . '"');
return $decoded !== null ? $decoded : $uni;
}
}
// 用法
$u = Unicode::encode('你好😀'); // \u4f60\u597d\ud83d\ude00
$d = Unicode::decode($u); // 你好😀
?>