5.2 PHP 6中的Unicode支持――《PHP高级程序设计:模式、框架和测试》
5.2 PHP 6中的Unicode支持
PHP 6中最大的一个变化就是引入了对Unicode文本编码的支持。在PHP中,Unicode改变了许多事情,这是因为字符串长度不再是其使用的存储空间的字节数了。Unicode中大量的字符可能是两个或多个字节的。为了支持多字节字符的字符串,PHP 6需要重写大多数字符串函数,例如strlen()。
5.2.1 Unicode语义
PHP 5中的字符串通常会为每个字符分配一个字节的空间(8位),但是在PHP 6中,字符串可以是Unicode 16位编码。8位编码以及所有其他你曾经用过的编码现在都会被当作二进制格式的字符串。新的正常的字符串被当作Unicode的。默认使用哪种字符串取决于php.ini文件中被称为unicode. semantics的设置。
当unicode. semantics设置为on时,正常的字符串文本是Unicode编码的。当它为off时,字符串文本被当作是8位的二进制字符串。我推荐大家使用Unicode语义。执行以下命令可以查看Unicode语义是关闭的还是打开的。
> php -r "echo ini_get('unicode.semantics');"
1
如果输出内容是0,将需要在php.ini文件中打开unicode.semantics。可以使用命令php -i来指定php.ini文件。如果在指定位置没有php.ini文件,PHP的发布包内置了一个示例文件。找到原始包中php.ini-recommended文件,将它改名并复制到由php -i指定的位置中,例如/etc/php.ini或者/usr/local/PHP 6/lib/php.ini。
一旦打开了Unicode语义,就可以在PHP脚本中直接使用Unicode字符了,像strlen()这样的函数会使用Unicode正确地计算出字符串的长度,而不是字符串中字节的数目。代码清单5-4演示了使用Canadian Aboriginal Syllabics文字的Unicode示例。
提示 Linux和Mac用户已经有一种兼容的字体,但是Windows用户需要到http://www.tiro.com查找一种这样的字体。没有合适的字体,代码清单5-4中的文字可能会被显示成方块或者空格。
代码清单5-4 Unicode字符串长度
$standard="abcde";
echo standard. " " . strlen($standard). "\n";
$unicode = "";
echo $unicode. " " . strlen(#unicode). "\n";
With unicode. semantics=off
abcde 5
15
With unicode.semantics=on
abcde 5
5
你会发现这些Unicode字符形成了一个长度为5的字符串。当关闭Unicode语义时,Unicode字符串的长度是15。
不过,在PHP 6中,就算关闭了Unicode.semantics,$unicode字符串仍然会被当作是Unicode编码的,所以会看到正确的输出结果。
在某些情况下,就算源码文件的内容是Unicode,而且Unicode语义也被打开了,你可能还是需要强制以二进制的方式处理字符串数据。代码清单5-5显示了与代码清单5-4中相同的Unicode字符串,但这里使用的是新的二进制字符串文本格式。
代码清单5-5 二进制字符串文本
$binary = b"";
echo $binary. " " . strlen($binary);
á..á..á..á..á.. 15
请大家注意,这里的输出结果假设输入的字符串是二进制的,这是因为在引号前面加了一个b字符。显示在屏幕上的输出结果是混乱的,这是因为二进制字符串的编码使用了php.ini文件中unicode.runtime_encoding设置的值。在这个例子中就是ISO-8859-1。
和其他类型的转换一样,你可以在二进制格式和Unicode格式之间转换,如代码清单5-6所示。
代码清单5-6 Unicode类型转换
$unicode = 'été';
echo $unicode;
$binary = (binary)$unicode;
echo $binary;
$unicode2 = (unicode) $binary;
echo $unicode2;
été
t
été
请大家注意,并非所有的字符都能够被转换到二进制格式。如果试图将代码清单5-4中的Canadian Aboriginal Syllabics文字的字符转换到二进制格式,你会发现所有的文字都被替换为问号字符了(字节的值为3f),这是因为问号标记是默认的错误替换字符。
5.2.2 Unicode排序规则
除了支持通用的Unicode之外,PHP 6还支持Unicode排序规则。Unicode排序规则的一个特性就是它允许按照一种特定语言或者区域的规则来给列表排序。代码清单5-7演示了基于传统的西班牙文字排序规则的排序,这里使用了扩展的30个字符的字母表,在这个字母表中ch、ll、ñ和rr等字符都被当作单独的字符。由于这些附加的字符,ll会排在l的后面,就像是字母b通常会排在字母a后面一样。
代码清单5-7 使用Unicode排序规则来排序
$list = array('luna','llaves','limonada');
//正常的字母排序,lla在 lu之前
sort($list);
print_r($list);
//合并排序, lla 在lu之后
locale_set_default('es_VE@collation=traditional');
sort($list, SORT_LOCALE_STRING);
print_r($list);
Array
(
[0] => limonada
[1] => llaves
[2] => luna
)
Array
(
[0] => limonada
[1] => luna
[2] => llaves
)
哪些方法会升级以支持Unicode语义还不是很清楚。fopen()函数应该会被更新,并扩展rt读取模式以读取Unicode文档。此外,大多数字符串方法也会被更新,如strlen()、str_word_count()等方法,并且能够使用不同的SPL迭代器以字符或者单词的方式去迭代访问字符串。
在http://www.php.net/Unicode中可以查到关于PHP 6中Unicode支持的更多信息。