某些多位元組編碼可以安全地用於 str_replace() 之類的功能,而其他則不行。僅僅確保所有涉及的字串都使用相同的編碼是不夠的:顯然它們必須使用相同的編碼,但這還不夠。它必須是正確的編碼類型。
UTF-8 是安全的編碼之一,因為它在構成編碼文字的位元組字串中,對於每個編碼字元的開始和結束位置的定義是明確的。某些編碼是不安全的:文字中一個字元的最後幾個位元組,後接下一個字元的前幾個位元組,可能會一起構成一個有效的字元。str_replace() 對於「字元」、「字元編碼」或「編碼文字」一無所知。它只知道位元組字串。對 str_replace() 而言,具有兩個位元組編碼的兩個相鄰字元看起來只像是一個四個位元組的序列,它不會知道它不應該嘗試匹配中間的兩個位元組。
雖然可以在現實世界中找到 str_replace() 損壞文字的例子,但可以使用 HTML-ENTITIES 編碼來說明。它不是安全的編碼之一。所有傳遞給 str_replace() 的字串都是有效的 HTML-ENTITIES 編碼文字,因此滿足了「所有輸入都使用相同編碼」的規則。
文字是「x<y」。它由位元組字串 [78 26 6c 74 3b 79] 表示。請注意,文字有三個字元,但字串有六個位元組。
<?php
$string = 'x<y';
mb_internal_encoding('HTML-ENTITIES');
echo "文字長度: ", mb_strlen($string), "\t字串長度: ", strlen($string), " ... ", $string, "\n";
$newstring = str_replace('l', 'g', $string);
echo "文字長度: ", mb_strlen($newstring), "\t字串長度: ", strlen($newstring), " ... ", $newstring, "\n";
$newstring = str_replace(';', ':', $string);
echo "文字長度: ", mb_strlen($newstring), "\t字串長度: ", strlen($newstring), " ... ", $newstring, "\n";
?>
即使「l」和「;」都沒有出現在文字「x<y」中,str_replace() 仍然找到了並更改了位元組。在一個案例中,它將文字更改為「x>y」,而在另一個案例中,它完全破壞了編碼。
我想,如果你可以的話,這是另一個使用 UTF-8 的理由。