一个PHP字符串只是一个字节序列,没有任何编码标记。字符串值可以来自各种来源:客户端(通过HTTP),数据库,文件或源代码中的字符串文字。PHP将所有这些读取为字节序列,并且从不提取任何编码信息。
只要所有数据源和目标都使用相同的编码,最糟糕的事情可能是字符串位置错误(如果使用多字节编码),因为PHP会计算字节而不是字符。
但是,如果编码不匹配(例如,您在存储为UTF-8的源文件中写入字符串文字,然后将其发送到需要Latin-1的数据库中),PHP将不会为您执行任何转换:愉快地复制原始字节。
最好的解决方案是这样的:
- 将PHP的内部编码设置为UTF-8。
- 将所有源文件另存为UTF-8。
- 使用UTF-8作为输出编码(不要忘记发送适当的
Content-type
标头)。
- 将数据库连接设置为使用UTF-8(
SET NAMES UTF8
在MySQL中)。
- 尽可能将其他所有配置为UTF-8。
- 对于您无法控制的任何内容(例如,第三方Web服务),请确保您知道该编码,并尽早转换为UTF-8,并尽可能晚地转换回另一种编码。
为什么选择UTF-8?因为它可以表示所有Unicode字符,从而取代了所有现有的7位和8位编码,并且因为它与ASCII二进制兼容,所以每个有效的ASCII字符串也是一个有效的UTF-8字符串(但不是vv )。
在您的示例中,将发生这种情况。
首先,保存您的源文件;您的文本编辑器可能配置为使用UTF-8,因此您的字符串文字最终以UTF-8编码在磁盘上。PHP读取该文件,并将字符串解释为一系列字节;$original
现在包含一个由7个字符组成的UTF-8编码字符串,这只是一个字节序列(尽管它包含7个以上的字节,因为每个字符由两个或多个字节表示)。如果您随后调用echo $original
,则编码后的字符串将按原样发送给客户端;如果您告诉客户期望使用UTF-8,那么一切都很好,但是如果没有,PHP将无法告诉您区别,最终您将在浏览器中产生垃圾。作为实验,请尝试以下操作:
$original = "शक्नोम्यत्तुम्";
echo strlen($original);
strlen
是与编码无关的,并且假定使用固定宽度的8位编码,即每个字符一个字节,因此它将计算字节,而不是字符。