0


PHP使用ltrim、rtrim以及trim处理中文时遇到的“坑”

说坑有点过分,更多的是自己写代码的时候,没有考虑全面,导致自己踩坑了。

案例复现

$source='CSDN科技';$source=rtrim($source,"】");

发现经过

rtrim

处理的字符串无法入库,检查后发现数据库报错信息:

General error: 1366 Incorrect string value: ‘xxxxxxx’ for column xxxxx

其实看到这个报错,就能立马意识到问题所在:字符串被不正确的截取,导致数据库驱动无法识别为正确的UTF8编码的文本。
而导致这问题的根本原因是

rtrim

以及一系列的方法是二进制安全的。
我们先把最后一个字符

的字节码打印出来:

var_dump(unpack('C*','技'));var_dump(unpack('C*','】'));//结果如下array(3){[1]=>int(230)[2]=>int(138)[3]=>int(128)}//技array(3){[1]=>int(227)[2]=>int(128)[3]=>int(145)}//】

其中的端倪:

的最后一个字节和

的第二个字节相同。

trim

方法是二进制安全的,会把

当做三个

字符

去递归处理原始文本,导致

的最后一个字节被截取,只剩两个字节,已经不是原来的

了,无法识别。
也就是说,只要原始字符串的尾部字节(包括递归处理后)包含在

trim

的第二个参数内,都会被依次递归处理。
下面这段代码跟我们最开始写的那段没有本质区别。

$source='anlige';$source=rtrim($source,"aeb");

解决方案

封装三个

mb

开头方法,去处理多字节编码的文本,逻辑比较暴力,代码有待优化。
注意:封装的

$char

参数是单个字符,有兴趣也可以修改成递归处理多个字符。

if(!function_exists('mb_ltrim')){functionmb_ltrim($str,$char){if(empty($str))return'';while(mb_substr($str,0,1)==$char){$str=mb_substr($str,1);}return$str;}}if(!function_exists('mb_rtrim')){functionmb_rtrim($str,$char){if(empty($str))return'';while(mb_substr($str,-1,1)==$char){$str=mb_substr($str,0,-1);}return$str;}}if(!function_exists('mb_trim')){functionmb_trim($str,$char){returnmb_rtrim(mb_ltrim($str,$char),$char);}}

总结

1、PHP大部分方法都是二进制安全的,因此在使用的时候要注意。
2、并不是二进制安全的方法都会遇到这个问题,主要是

trim

系列的特殊处理方式:根据第二个参数传递的值,递归处理首尾字符。
3、遇到问题不可怕,能迅速想到问题的来源和解决方案才最重要的。

标签: php trim

本文转载自: https://blog.csdn.net/Anlige/article/details/120360920
版权归原作者 Anlige 所有, 如有侵权,请联系我们删除。

“PHP使用ltrim、rtrim以及trim处理中文时遇到的“坑””的评论:

还没有评论