PHP中文字符串需借助拼音扩展(如overtrue/pinyin)转首字母后排序,原生sort按Unicode码点排不满足需求;abbr()获取首字母,注意大小写、多音字及二级排序。

PHP 中文字符串怎么按拼音首字母排序
PHP 原生不支持中文拼音排序,sort() 或 usort() 直接对中文数组排序,结果是按 Unicode 码点排(比如“张”“李”“王”会变成“李”“王”“张”),不是按“L、W、Z”拼音顺序。必须先将汉字转为对应拼音(或首字母),再参与比较。
用 pinyin() 扩展最稳妥,但得先装扩展
推荐使用开源的 overtrue/pinyin Composer 包,它基于词库+规则,比纯 GBK/Unicode 映射准确得多(比如能区分“重庆”的“重”读 chong 而非 zhong)。
安装命令:
composer require overtrue/pinyin
基本用法示例:
立即学习“PHP免费学习笔记(深入)”;
$pinyin = new \Overtrue\Pinyin\Pinyin();
$names = ['张三', '李四', '重庆', '西安'];
usort($names, function($a, $b) use ($pinyin) {
$aFirst = $pinyin->abbr($a); // 返回首字母,如 'z'
$bFirst = $pinyin->abbr($b);
return strcmp($aFirst, $bFirst);
});
注意点:
-
abbr()默认返回小写首字母,如需大写可用->abbr($str, true) - 若字符串含英文/数字,
abbr()会原样保留首字符,不会报错 - 遇到生僻字或未登录词,会 fallback 到单字拼音,不是空字符串
不用扩展?iconv('UTF-8', 'ASCII//TRANSLIT', $str) 不靠谱
有人试过用 iconv 做拉丁化转换,但 PHP 的 ASCII//TRANSLIT 在中文上基本失效——它主要处理西欧字符(如 é → e),对汉字直接返回空或问号,不能用于拼音排序。
常见错误现象:
-
iconv('UTF-8', 'ASCII//TRANSLIT', '张')返回空字符串或FALSE - 即使部分环境返回了类似
Zhang,也是不可靠的 libc 行为,不同系统结果不一致 - 无法控制大小写、不支持多音字、无词库支撑
数据库层排序更高效,但依赖 MySQL 8.0+ 或 PostgreSQL
如果数据来自 MySQL,且版本 ≥ 8.0,可直接用 COLLATE utf8mb4_unicode_ci 配合拼音排序规则(需启用 utf8mb4_pinyin_ci,但该 collation 并非 MySQL 官方内置,需自行编译或用 AliSQL/TiDB 等分支)。
更通用的做法是:在表中加一个 pinyin_first 字段(VARCHAR(1)),写入时用 PHP 扩展计算并存入,查询时 ORDER BY pinyin_first, name。这样避免每次 SELECT 都调用拼音转换,性能明显更好。
容易忽略的一点:拼音首字母排序只是“一级排序”,同字母下(如“李四”“李白”)应补二级排序(比如按完整拼音或原始字符串),否则顺序不稳定。



















