说坑有点过分,更多的是自己写代码的时候,没有考虑全面,导致自己踩坑了。
案例复现
$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
参数是单个字符,有兴趣也可以修改成递归处理多个字符。文章来源:https://www.toymoban.com/news/detail-430202.html
if(!function_exists('mb_ltrim')){
function mb_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')){
function mb_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')){
function mb_trim($str, $char){
return mb_rtrim(mb_ltrim($str, $char), $char);
}
}
总结
1、PHP大部分方法都是二进制安全的,因此在使用的时候要注意。
2、并不是二进制安全的方法都会遇到这个问题,主要是trim
系列的特殊处理方式:根据第二个参数传递的值,递归处理首尾字符。
3、遇到问题不可怕,能迅速想到问题的来源和解决方案才最重要的。文章来源地址https://www.toymoban.com/news/detail-430202.html
到了这里,关于PHP使用ltrim、rtrim以及trim处理中文时遇到的“坑”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!