在中文系統開發中,漢字轉拼音是常見需求:如用戶姓名排序、搜尋索引、URL 別名生成等。本文提供一個功能完整、效能優異的 Helper_Spell 類,支援全拼輸出、首字母模式、大小寫切換,並內建 UTF-8 字串分割與拼音映射表載入。
str_split 中文亂碼問題)<?php
class Helper_Spell {
/** 拼音映射表(需對應 pytable_without_tune.txt 序列化檔案) */
public static $spellArray = [];
/** 載入拼音映射表 */
public static function getArray(): array {
if (empty(self::$spellArray)) {
$file = __DIR__ . '/pytable_without_tune.txt';
if (!file_exists($file)) {
throw new RuntimeException("拼音映射表檔案不存在:$file");
}
self::$spellArray = unserialize(file_get_contents($file));
}
return self::$spellArray;
}
/**
* 獲取字串首字拼音
* @param string $string 待轉換字串
* @param bool $isOne true=僅取首字母,false=取全拼
* @param bool $upper true=大寫,false=小寫
* @return string
*/
public static function getChineseFirstChar(string $string, bool $isOne = false, bool $upper = false): string {
$spellArray = self::getArray();
$chars = self::utf8_str_split($string, 1);
if (empty($chars)) return '';
$firstChar = $chars[0];
// 判斷是否為漢字(CJK 統一表意文字基本區)
if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $firstChar)) {
$pinyin = $spellArray[$firstChar] ?? $firstChar;
$result = $pinyin[0] ?? $firstChar;
} else {
$result = $firstChar;
}
$result = $isOne ? substr($result, 0, 1) : $result;
return $upper ? strtoupper($result) : strtolower($result);
}
/**
* 將字串轉為拼音(空格分隔)
* @param string $string 待轉換字串
* @param bool $isOne true=各字僅取首字母,false=取全拼
* @param bool $upper true=大寫,false=小寫
* @return string
*/
public static function getChineseChar(string $string, bool $isOne = false, bool $upper = false): string {
$spellArray = self::getArray();
$chars = self::utf8_str_split($string, 1);
$result = [];
foreach ($chars as $char) {
if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $char)) {
$pinyin = $spellArray[$char] ?? $char;
$pinyin = $pinyin[0] ?? $char;
} else {
$pinyin = $char;
}
$pinyin = $isOne ? substr($pinyin, 0, 1) : $pinyin;
$result[] = $upper ? strtoupper($pinyin) : strtolower($pinyin);
}
return implode(' ', $result);
}
/**
* UTF-8 安全字串分割
* @param string $str
* @param int $split_len 每段字符數
* @return array|false
*/
private static function utf8_str_split(string $str, int $split_len = 1): array|false {
if ($split_len < 1) return false;
$len = mb_strlen($str, 'UTF-8');
if ($len <= $split_len) return [$str];
// 使用正則按字符分割
preg_match_all('/.{'.$split_len.'}|[^\x00]{1,'.$split_len.'}$/us', $str, $matches);
return $matches[0] ?? [];
}
}
// 使用範例
echo Helper_Spell::getChineseFirstChar('我是作者'); // wo
echo Helper_Spell::getChineseFirstChar('我是作者', true); // w
echo Helper_Spell::getChineseFirstChar('我是作者', true, true); // W
echo Helper_Spell::getChineseChar('我是作者'); // wo shi zuo zhe
echo Helper_Spell::getChineseChar('我是作者', true); // w s z z
echo Helper_Spell::getChineseChar('我是作者', true, true); // W S Z Z
echo Helper_Spell::getChineseChar('我是作者', false, true); // WO SHI ZUO ZHE
?>
類別依賴 pytable_without_tune.txt 檔案,該檔案為序列化的 PHP 陣列,Key 為漢字,Value 為對應拼音陣列(含多音字)。你可以從開源專案(如 overtrue/pinyin)獲取或自行整理。
utf8_str_split() 使用 preg_match_all 搭配 /u 修飾符,正確處理多位元組字符,避免 str_split 將單個漢字拆成 3 個亂碼字節。
遇到英文、數字、標點等非漢字字符,直接保留原樣,確保混合字串(如「PHP 7.0」)轉換結果合理。
$spellArray 避免重複載入檔案。pinyin PHP 擴展或使用 overtrue/pinyin Composer 套件(底層用 C 實現,速度更快)。getArray(),避免首次請求延遲。getChineseFirstChar($name, true, true) 獲取首字母大寫作為排序依據。strtolower(str_replace(' ', '-', Helper_Spell::getChineseChar($title))) 產生友善網址。這個工具類輕量、無依賴、易整合,適合中小型專案直接引入使用。若專案規模龐大或對效能極度敏感,建議改用成熟的 Composer 套件以獲得更完善的多音字處理與維護保障。