GBK 編碼中,漢字佔兩個位元組,高位元組 0x81-0xFE,低位元組 0x40-0xFE(除 0x7F)。將雙位元組轉為單一整數 code = high * 256 + low - 65536,落入特定範圍即對應拼音首字母。
<?php
/**
* 取得單一漢字的拼音首字母(大寫)
* 僅支援 GBK/CP936 編碼輸入
* @param string $char 單一漢字(GBK 編碼)
* @return string 首字母 A-Z,非漢字回傳原字元
*/
function getPinyinInitial(string $char): string {
if (strlen($char) !== 2) return $char; // 非雙位元組字元
$high = ord($char[0]);
$low = ord($char[1]);
// 非漢字區範圍
if ($high < 0x81 || $high > 0xFE || $low < 0x40 || $low > 0xFE || $low === 0x7F) {
return $char;
}
$code = $high * 256 + $low - 65536;
// 區位碼對映表(GBK 標準)
static $map = [
[45217, 45252, 'A'], [45253, 45760, 'B'], [45761, 46317, 'C'],
[46318, 46825, 'D'], [46826, 47009, 'E'], [47010, 47296, 'F'],
[47297, 47613, 'G'], [47614, 48118, 'H'], [48119, 49061, 'J'],
[49062, 49323, 'K'], [49324, 49895, 'L'], [49896, 50370, 'M'],
[50371, 50613, 'N'], [50614, 50621, 'O'], [50622, 50905, 'P'],
[50906, 51386, 'Q'], [51387, 51445, 'R'], [51446, 52217, 'S'],
[52218, 52697, 'T'], [52698, 52979, 'W'], [52980, 53640, 'X'],
[53689, 54480, 'Y'], [54481, 62289, 'Z'],
];
foreach ($map as [$min, $max, $initial]) {
if ($code >= $min && $code <= $max) return $initial;
}
return $char;
}
/**
* 取得字串每個漢字的首字母組合
* @param string $str GBK 編碼字串
* @return string 如 "中華人民共和國" => "ZHRMGHG"
*/
function getPinyinInitials(string $str): string {
$result = '';
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
$char = $str[$i];
$high = ord($char);
if ($high >= 0x81 && $high <= 0xFE) { // 雙位元組漢字
if ($i + 1 < $len) {
$result .= getPinyinInitial($str[$i] . $str[$i+1]);
$i++;
} else {
$result .= $char; // 殘缺位元組
}
} else {
$result .= $char; // ASCII 字元保留
}
}
return $str;
}
// 使用範例
$str = '中華人民共和國'; // 檔案必須儲存為 GBK/CP936
echo getPinyinInitials($str); // 輸出: ZHRMGHG
'中華' 為 6 位元組,演算法完全失效// composer require overtrue/pinyin
use Overtrue\Pinyin\Pinyin;
$pinyin = new Pinyin();
// 預設輸出:['Zhong', 'Hua', 'Ren', 'Min', 'Gong', 'He', 'Guo']
$initials = $pinyin->initials('中華人民共和國'); // ZHRMGHG
$firstLetters = $pinyin->firstLetters('中華人民共和國'); // ZHRMGHG
$permalink = $pinyin->permalink('中華人民共和國'); // zhong-hua-ren-min-gong-he-guo
// 支援多種輸出格式
$pinyin->convert('帶英文ABC', PINYIN_ASCII_ONLY); // 'dai ying wen ABC'
$pinyin->convert('帶聲調', PINYIN_TONE); // 'dài shēng diào'
$pinyin->convert('帶數字123', PINYIN_KEEP_NUMBER); // 'dai shu zi 123'
| 特性 | GBK 區位碼法 | overtrue/pinyin |
|---|---|---|
| 編碼要求 | GBK 檔案/字串 | UTF-8 字串(現代標準) |
| 多音字處理 | 無(單一映射) | 支援(詞庫歧義消解) |
| 非漢字處理 | 保留原字元 | 可配置保留/移除/轉換 |
| 效能 | 極快(純運算) | 快(詞庫索引,需載入) |
| 維護性 | 硬編碼範圍,難擴展 | 詞庫可更新、社群維護 |
| 依賴 | 無 | Composer 套件 |
<?php
// 內建少量常用漢字首字母映射(UTF-8 版)
$pinyinMap = [
'中' => 'Z', '華' => 'H', '人' => 'R', '民' => 'M', '共' => 'G',
'和' => 'H', '國' => 'G', '北' => 'B', '京' => 'J', '上' => 'S',
'海' => 'H', '台' => 'T', '灣' => 'W', // ... 依需求擴展
];
function simpleInitials(string $str, array $map): string {
$result = '';
$len = mb_strlen($str, 'UTF-8');
for ($i = 0; $i < $len; $i++) {
$char = mb_substr($str, $i, 1, 'UTF-8');
$result .= $map[$char] ?? $char;
}
return $result;
}
// 使用:simpleInitials('中華人民共和國', $pinyinMap); // ZHRMGHG
pinyin_initial 存首字母,ORDER BY pinyin_initial, namepermalink() 產生 SEO 友善連結