mb_substr比substr安全,因其按字符而非字节截取,避免UTF-8中文乱码;需显式传入正确编码(如'UTF-8'),并确保mbstring扩展已启用。

mb_substr 为什么比 substr 安全
PHP 默认的 substr 按字节切,中文 UTF-8 下一个字占 3 字节,切在中间就变乱码。比如 "你好" 的 UTF-8 是 6 字节,substr($str, 0, 2) 可能只取到第一个汉字的前两个字节,输出 。
mb_substr 知道字符边界,按“字符”而非“字节”截取,天然支持 UTF-8 中文。
- 必须显式传入编码,如
mb_substr($str, 0, 5, 'UTF-8');不传或传错(如'utf8'少横线)会退化成字节行为 - PHP 8.0+ 默认启用
mbstring扩展,但老环境要确认已开启:extension=mbstring在php.ini中未被注释 - 如果字符串来源不可控(如用户输入、数据库字段),一律用
mb_substr,别依赖mb_internal_encoding()全局设编码
截到一半 HTML 标签怎么办
直接对含 HTML 的字符串用 mb_substr,可能把 <p> 截成 <p 或 >,破坏结构甚至引发 XSS 风险。
得先剥离 HTML,再截取,最后可选是否补回标签闭合 —— 但更稳妥的是「截取纯文本」。
立即学习“PHP免费学习笔记(深入)”;
- 用
strip_tags($html)去掉所有标签,再用mb_substr截取:避免标签断裂 - 若需保留部分格式(如 zuojiankuohaophpcnstrong>),可用
preg_replace清理危险标签,但注意正则无法完美解析嵌套 HTML - 别用
html_entity_decode后再截 —— 实体如会被当普通字符计数,导致长度偏差
性能差?可能是 mbstring 设置拖慢了
mb_substr 比 substr 慢,尤其长文本+多语言混合时。瓶颈常不在函数本身,而在 mbstring 的内部编码检测逻辑。
- 强制指定
encoding参数(如'UTF-8'),禁止它调用mb_detect_encoding - 避免在循环里反复调用
mb_internal_encoding('UTF-8')—— 改为一次设置,或直接传参 - 如果确定全是 ASCII 或纯中文 UTF-8,且长度可控,可考虑先用
strlen判断是否超长,再决定是否进mb_substr
替代方案:用 iconv_substr 要小心
有些老项目用 iconv_substr,它也支持多字节,但行为和 mb_substr 不完全一致。
-
iconv_substr对非法 UTF-8 字节会静默跳过或替换为?,而mb_substr默认报错(mb_substitute_character('none')可改) - 参数顺序不同:
iconv_substr($str, $start, $length, $encoding),$length单位仍是字符,但某些 PHP 版本对超长$length处理异常 - PHP 8.2 起
iconv扩展默认禁用,除非明确启用,否则调用直接报Fatal error: Uncaught Error: Call to undefined function iconv_substr()
mb_substr 却没生效,八成卡在这两处。











