PHP函数记录-trim导致的编码异常

最近写业务接口报500,排查发现是编码问题导致 laravel response异常。

起初以为是DB编码导致,排除后发现了是代码中的trim导致的

//给到前端纯洁的数据  之前有拼接¥%等标识
public function normalField($data)
{
        $charlist = '%¥';
        foreach ($data as $tag => &$item) {
                           array_walk_recursive($item, function (&$value) use ($charlist) {
                    if (is_scalar($value)) {
                        $value = trim($value, $charlist);
                    }
                });
            break;
        }

官方文档

trim不是多字节的,比如中文相关的 utf8大部分是三个字节
这里用到了 ¥ 和字符串 包含了运营
即 trim(’运营’, ‘%¥’)

        $trim = '¥ 营';
        for ($i = 0; $i< strlen($trim);$i++){
            echo sprintf("字节%s对应的asc码%d,16进制:%s", $trim[$i],ord($trim[$i]), base_convert(ord($trim[$i]), 10, 16)) .PHP_EOL;
        }
字节�对应的asc码239,16进制:ef
字节�对应的asc码191,16进制:bf
字节�对应的asc码165,16进制:a5
字节 对应的asc码32,16进制:20
字节�对应的asc码232,16进制:e8
字节�对应的asc码144,16进制:90
字节�对应的asc码165,16进制:a5

发现问题 尾字节 都是a5 trim会把误伤 营的a5

¥对应的三个字节是 ef  bf  a5
营 对应的三个字节是 e8 90 a5

文档有提示作用机制

Note: Possible gotcha: removing middle characters
Because trim() trims characters from the beginning and end of a string, it may be 
confusing when characters are (or are not) removed from the middle. trim('abc', 'bad') 
removes both 'a' and 'b' because it trims 'a' thus moving 'b' to the beginning to also be 
trimmed. So, this is why it "works" whereas trim('abc', 'b') seemingly does not.

解决方式

  1. 自定义 mb_trim

参考

PHP字符串与字节转换示例
PHP trim乱码原因

你可能感兴趣的:(PHP,php)