我正在使用php中的多语言应用程序。
一切都很好,直到最近才被要求支持中文字符。我为支持UTF-8字符而采取的措施如下:
所有数据库表现在都是UTF-8
HTML模板包含标记<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
控制器发出一个标题,指定用于http响应的编码(utf-8)
一切都很好,直到我开始进行一些字符串操作(substr等)
使用中文它将无法工作,因为中文表示为多字节,因此如果你做一个正常的子字符串(substr),它会在分配的字节之一和f * ck up中间切割一个“字母”屏幕上的结果。
我通过在引导程序
中添加此问题来修复我的所有问题 mb_internal_encoding("UTF-8");
并将所有strlen
,substr
,strstr
替换为mb_
对应的人。
在php中完全支持UTF-8需要做些什么?
答案 0 :(得分:8)
除了更换这些功能之外还有一点点。
正则表达式
您应该将utf8标志添加到所有可以包含非Ascii字符的字符串的PCRE正则表达式中,以便将模式解释为实际字符而不是字节。
$subject = "Helló";
$pattern = '/(l|ó){2,3}/u'; //The u flag indicates the pattern is UTF8
preg_match($pattern, substr($subject,3), $matches, PREG_OFFSET_CAPTURE);
如果你希望你的正则表达式对于非拉丁字母表是正确的,你应该使用Unicode character classes而不是标准的Perl吗?
有很多不同的Unicode字符类,其中一些对于习惯用拉丁字母读写的人来说非常不寻常。例如,一些characters combine with the previous字符可以创建一个新的字形。对它们的更多解释可以是read here。
虽然mbstring扩展中有正则表达式函数,但不建议使用它们。标准PCRE功能可以正常使用UTF8标志。
功能替换
虽然你的列表是一个开头,但我到目前为止找到的需要用多字节版本替换的函数列表更长。这是具有替换函数的函数列表,其中一些函数未在PHP中定义,但可从Github as mb_extra处获得。
$unsafeFunctions = array(
'mail' => 'mb_send_mail',
'split' => null, //'mb_split', deprecated function - just don't use it
'stripos' => 'mb_stripos',
'stristr' => 'mb_stristr',
'strlen' => 'mb_strlen',
'strpos' => 'mb_strpos',
'strrpos' => 'mb_strrpos',
'strrchr' => 'mb_strrchr',
'strripos' => 'mb_strripos',
'strstr' => 'mb_strstr',
'strtolower' => 'mb_strtolower',
'strtoupper' => 'mb_strtoupper',
'substr_count' => 'mb_substr_count',
'substr' => 'mb_substr',
'str_ireplace' => null,
'str_split' => 'mb_str_split', //TODO - check this works
'strcasecmp' => 'mb_strcasecmp', //TODO - check this works
'strcspn' => null, //TODO - implement alternative
'strrev' => 'mb_strrev', //TODO - check this works
'strspn' => null, //TODO - implement alternative
'substr_replace'=> 'mb_substr_replace',
'lcfirst' => null,
'ucfirst' => 'mb_ucfirst',
'ucwords' => 'mb_ucwords',
'wordwrap' => null,
);
<强>的MySQL 强>
虽然您可能认为将字符类型设置为utf8
会在MySQL中为您提供UTF-8支持,但事实并非如此。
它只支持UTF-8,它最多可编码3个字节,即Basic Multi-lingual Plane。然而,人们正在积极使用需要4个字节进行编码的字符,包括大多数Emoji characters,也称为Supplementary Multilingual Plane
为了支持这些,您通常应该使用:
对于特定场景,可能有适合您的备用排序规则集,但通常会坚持最正确的排序规则集。
您应在MySQL配置文件中设置字符集和排序规则的位置列表:
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4
[mysqld]
init-connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
在所有情况下可能都不需要SET NAMES
- 但只需要很小的速度惩罚就更安全。
PHP INI文件
虽然你说你已经在你的bootstrap脚本中设置了mb_internal_encoding,但是在PHP ini文件中这样做要好得多,并且还设置了所有推荐的参数:
mbstring.language = Neutral ; Set default language to Neutral(UTF-8) (default)
mbstring.internal_encoding = UTF-8 ; Set default internal encoding to UTF-8
mbstring.encoding_translation = On ; HTTP input encoding translation is enabled
mbstring.http_input = auto ; Set HTTP input character set dectection to auto
mbstring.http_output = UTF-8 ; Set HTTP output encoding to UTF-8
mbstring.detect_order = auto ; Set default character encoding detection order to auto
mbstring.substitute_character = none ; Do not print invalid characters
default_charset = UTF-8 ; Default character set for auto content type header
帮助浏览器为表单选择UTF8
您需要将表单上的accept-charset设置为UTF-8,以告知浏览器将其提交为UTF8。
在您的form in a hidden field中添加UTF8字符,以阻止Internet Explorer(5,6,7和8)将表单提交为UTF8以外的其他内容。
<强>其它强>
如果您正在使用Apache设置“AddDefaultCharset utf-8”
正如您所说的那样,但只是为了提醒任何人阅读答案,请在标题中设置元内容类型。
那应该是关于它的。虽然值得阅读“What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text”页面,但我认为它优于use UTF-8 everywhere,因此不必花费任何精力去处理不同的字符集。