通訊錄索引、城市列表分組、標籤雲分類等需要按首字母分組的功能。
<?php
function getFirstLetter($str) {
if (empty($str)) return '';
$firstChar = $str[0];
$ord = ord($firstChar);
// 數字、英文直接返回大寫
if ($ord >= 48 && $ord <= 57) return $firstChar; // 0-9
if ($ord >= 65 && $ord <= 90) return $firstChar; // A-Z
if ($ord >= 97 && $ord <= 122) return strtoupper($firstChar); // a-z
// 中文處理:需為 UTF-8 編碼
if ($ord > 128) {
return getPinyinInitial($str);
}
return '#'; // 其他符號歸類
}
function getPinyinInitial($chinese) {
// 確保 UTF-8 轉 GB2312
$gb = iconv("UTF-8", "GB2312//IGNORE", $chinese);
if (strlen($gb) < 2) return '#';
// 計算區位碼
$asc = ord($gb[0]) * 256 + ord($gb[1]) - 65536;
// 拼音首字母區間對照表
$pinyinMap = [
[-20319, -20284, 'A'], [-20283, -19776, 'B'], [-19775, -19219, 'C'],
[-19218, -18711, 'D'], [-18710, -18527, 'E'], [-18526, -18240, 'F'],
[-18239, -17923, 'G'], [-17922, -17418, 'H'], [-17417, -16475, 'J'],
[-16474, -16213, 'K'], [-16212, -15641, 'L'], [-15640, -15166, 'M'],
[-15165, -14923, 'N'], [-14922, -14915, 'O'], [-14914, -14631, 'P'],
[-14630, -14150, 'Q'], [-14149, -14091, 'R'], [-14090, -13319, 'S'],
[-13318, -12839, 'T'], [-12838, -12557, 'W'], [-12556, -11848, 'X'],
[-11847, -11056, 'Y'], [-11055, -10247, 'Z']
];
foreach ($pinyinMap as [$start, $end, $letter]) {
if ($asc >= $start && $asc <= $end) return $letter;
}
return '#';
}
// 批量處理範例
$titles = ['北京', '上海', '123數字', 'Apple', 'apple', '你好世界'];
foreach ($titles as $title) {
echo $title . ' => ' . getFirstLetter($title) . "\n";
}
/* 輸出:
北京 => B
上海 => S
123數字 => 1
Apple => A
apple => A
你好世界 => N
*/
<?php
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test;charset=utf8", 'user', 'pass');
$stmt = $pdo->query("SELECT title FROM articles");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$initial = getFirstLetter($row['title']);
$groups[$initial][] = $row['title'];
}
ksort($groups); // 按首字母排序
// 輸出 A-Z 分組導航...
initial CHAR(1)),寫入時計算一次iconv 需確認伺服器安裝 libiconv 擴展#overtrue/pinyin 等 Composer 套件,支援多音字與更完整字庫