ord()仅返回字符串首字节的0–255整数值,不解析编码,对UTF-8中文或emoji(如'中'→228)返回的是字节值而非Unicode码点,仅适用于ASCII等单字节编码场景。

ord() 只能取字符串第一个字节的 0–255 整数值,不是“字符的 ASCII 码”,更不是“Unicode 码点”——用错场景会直接导致中文、emoji 处理出错。
ord() 的真实行为:只读第一个字节
它不解析编码,不识别 UTF-8 多字节结构,只是把 $string[0] 当作一个字节,原样转成整数。比如:
echo ord('中'); // 输出 228(UTF-8 编码首字节,不是汉字“中”的 Unicode 值)
常见错误现象:
- 对
'中文'调ord()得到 228,以为是 bug,其实是预期行为 - 用
ord()判断中文字符个数,结果算成 3 个(实际是 1 个 UTF-8 字符,占 3 字节) - 在 ThinkPHP 里封装
Str::toAscii()这种不存在的方法,白忙活
什么时候可以用 ord() 安全?
仅当明确处理单字节编码(ASCII、ISO-8859-1、Windows-1252)或纯英文/数字/标点输入时才可靠:
立即学习“PHP免费学习笔记(深入)”;
- 校验 HTTP header 字符是否为可打印 ASCII(
ord($c) >= 32 && ord($c) ) - 解析二进制协议头(如自定义 TCP 包前 4 字节是长度字段,用
ord()+substr()拆解) - 生成简单哈希种子:
ord($str[0]) ^ ord($str[1])(只要不依赖语义,只图快) - 配合
chr()做字节级加解密(如凯撒移位)
想真正获取中文或 emoji 的 Unicode 码点?别硬套 ord()
必须换函数,否则拿到的永远是乱码字节值:
- PHP 7.2+ 直接用
mb_ord():mb_ord('中', 'UTF-8')→20013(U+4E2D) - PHP < 7.2 且无 mbstring 扩展?用
unpack('n*', mb_convert_encoding($char, 'UCS-2BE', 'UTF-8')) - 需要兼容性更强?改用
IntlChar::ord()(需启用 intl 扩展) - 批量处理字符串每个字符?别用
str_split()+ord(),改用preg_match_all('//u', $str, $matches)再逐个mb_ord()
最容易被忽略的一点
业务里所谓“把字符串转成 ASCII 数组”,90% 场景其实只需要前几个字母做快速标识(如缓存 key 前缀),这时 array_map('ord', str_split(substr($s, 0, 4))) 完全够用;但一旦涉及用户昵称、评论、搜索词,就必须立刻切换到 mb_ord() 或明确约定输入只接受 ASCII —— 混用会导致截断、乱码、校验绕过等线上问题。



















