運行以下代碼
$tag = "互聯(lián)網(wǎng)產(chǎn)品、";
$text = rtrim($tag, "、");
print_r($text);
我們可能以為會得到的結(jié)果是互聯(lián)網(wǎng)產(chǎn)品,實際結(jié)果是互聯(lián)網(wǎng)產(chǎn)?。為什么會這樣呢?
原理
trim 函數(shù)文檔
string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )
該函數(shù)不是多字節(jié)函數(shù),也就是說,漢字這樣的多字節(jié)字符,會拿其頭或尾的單字節(jié)來和后面的$character_mask對應的char數(shù)組進行匹配,如果在后面的數(shù)組中,則刪掉,繼續(xù)匹配。比如:
echo ltrim("bcdf","abc"); // df
如下面的 demo 中的函數(shù)string_print_char所示:
、 由0xe3 0x80 0x81三字節(jié)組成,
品 由0xe5 0x93 0x81三字節(jié)組成。
所以在執(zhí)行rtrim的時候,通過字節(jié)比對,會將0x81去掉,導致了最后出現(xiàn)了亂碼。
解決方案
封裝方法:
public static function mb_rtrim($string, $trim, $encoding)
{
$mask = [];
$trimLength = mb_strlen($trim, $encoding);
for ($i = 0; $i < $trimLength; $i++) {
$item = mb_substr($trim, $i, 1, $encoding);
$mask[] = $item;
}
$len = mb_strlen($string, $encoding);
if ($len > 0) {
$i = $len - 1;
do {
$item = mb_substr($string, $i, 1, $encoding);
if (in_array($item, $mask)) {
$len--;
} else {
break;
}
} while ($i-- != 0);
}
return mb_substr($string, 0, $len, $encoding);
}
mb_internal_encoding("UTF-8");
$tag = "互聯(lián)網(wǎng)產(chǎn)品、";
$encoding = mb_internal_encoding();
print_r(mb_rtrim($tag, "、",$encoding));