substr()按字节截取,处理中文易乱码;mb_substr()按字符截取且需显式指定UTF-8编码;截取异常时应优先检查HTML声明、文件编码及数据库字符集。

substr() 是最常用也最容易出错的字符串截取函数
PHP 里截字符串,substr() 是绕不开的起点。但它不是“安全”的:传入负数偏移、长度超限、多字节字符(比如中文)都会导致意外结果。
关键点在于:substr() 按**字节**操作,不是按字符。UTF-8 编码下,一个中文占 3 字节,用 substr($str, 0, 2) 可能切出乱码。
- 只用于 ASCII 或已确认单字节编码的场景(如纯英文日志)
- 起始位置为负数时,从末尾倒数计算,但长度仍从该位置向后取字节
- 长度参数可省略,表示“截到末尾”,但若起始位置越界,返回空字符串而非报错
echo substr("hello世界", 0, 5); // 输出 "hello"(前 5 字节)
echo substr("hello世界", 0, 7); // 输出 "hello"("世"字被截断,出现)
mb_substr() 才是处理中文等多字节字符串的正确选择
要安全截取含中文、日文、emoji 的字符串,必须用 mb_substr(),并显式指定编码(通常是 'UTF-8')。
它按**字符数**截取,不是字节数。但注意:它不会自动检测编码,不传第四个参数或传错编码(比如写成 'utf8' 而非 'UTF-8'),照样出错。
立即学习“PHP免费学习笔记(深入)”;
- 第四个参数(编码)强烈建议显式写出,不要依赖
mb_internal_encoding() - 起始位置和长度都以“字符”为单位,负数同样支持从末尾计数
- 如果字符串本身不是 UTF-8,先用
mb_convert_encoding()转换,别硬套
echo mb_substr("hello世界", 0, 5, 'UTF-8'); // 输出 "hello"
echo mb_substr("hello世界", 5, 2, 'UTF-8'); // 输出 "世界"
遇到截取后显示或乱码,优先检查这三件事
不是函数写错了,大概率是环境或数据层面的问题。
- 网页 HTML 响应头或
是否声明为UTF-8?否则浏览器渲染就乱 - PHP 文件本身是否保存为 UTF-8 无 BOM 格式?编辑器里看一眼编码选项
- 数据库字段、连接、查询是否统一设为
utf8mb4?特别是存 emoji 时,utf8在 MySQL 中实际只支持 3 字节,会丢数据
简单需求别硬套函数:用 explode() + array_slice() 更直观
如果只是按分隔符(比如逗号、换行符)取前几段,explode() 配合 array_slice() 往往比算偏移更可靠、更易读。
尤其适合处理 CSV 片段、日志行、URL 参数等结构化文本片段。
- 避免手动计算分隔符位置和长度,减少边界错误
-
array_slice()支持负数索引,取最后 N 段也很方便 - 记得用
implode()把结果拼回去,否则输出的是数组
$line = "a,b,c,d,e";
$parts = explode(',', $line);
$first_three = array_slice($parts, 0, 3);
echo implode(',', $first_three); // 输出 "a,b,c"
PHP 字符串截取真正的复杂点不在函数怎么写,而在你是否清楚当前字符串的编码、来源、预期展示环境——这三个条件缺一,substr() 和 mb_substr() 都会给你“看似运行成功,实则结果错误”的假象。











