PHP函数mb_substr关于字符编码的一个坑

在导入数据的时候,总是有些数据导入失败,检查发现原因是json_encode失败,通过json_last_error发现是错误原因是JSON_ERROR_UTF8,但是检查了一下参数的编码,是UTF8的没问题。查看PHP文档,这个错误的原因是:异常的 UTF-8 字符,也许是因为不正确的编码。又仔细检查了一下,发现是其中一个字段有问题,这个字段是通过mb_substr函数截取正文的字符得到的。

再仔细的看一下,似乎截取的有些不对。比如下面的代码:

$str = '北京市朝阳区';
var_dump(mb_substr($str,0,3));

预期输出是:string(9) "北京市",但是输出确是:string(3) "北"。

如果我修改一下要截取的字符数量为2:

$str = '北京市朝阳区';
var_dump(mb_substr($str,0,2));

预期输出是:string(6) "北京",但是输出确是:string(2) "劢

原因是因为mb_substr这个函数在操作的时候如果没有传字符编码,则按照默认的内部编码操作字符串。PHP5.6之前的默认编码都是ISO-8859-1,5.6之后的才是UTF8,UTF8模式下,一个中文字符占3个字节,而ISO-8859-1则是按照一个字节进行处理,所以自然取出来的是异常的字符串。

所以在处理的时候,最好直接指定编码,详细的可以看下官方文档

PHP有的地方真的是比较坑,很多时候不抛出异常,比如json_encode失败的时候为什么不抛出异常啊……