迁移一个处理UTF-8的php应用程序
迁移一个处理UTF-8的php应用程序
我正在开发一个使用PHP的多语言应用程序。
一切都很顺利,直到最近被要求支持中文字符。为了支持UTF-8字符,我采取了以下措施:
- 所有数据库表现在都是UTF-8编码
- HTML模板中包含标签
- 控制器发送一个指定编码(utf-8)的头部,用于HTTP响应
一切都好,直到我开始进行一些字符串操作(如substr等)。
对于中文来说,这样做行不通,因为中文是由多个字节表示的,所以如果你使用普通的子字符串(substr),它可能会在一个字节分配的字符中间截断一个“字母”,导致结果在屏幕上出错。
通过在引导文件中添加以下代码mb_internal_encoding("UTF-8");
并将所有的strlen
,substr
,strstr
替换为它们的mb_
相应函数,我解决了所有问题。
还有哪些事情我需要做来完全支持PHP中的UTF-8编码?
问题:将一个php应用程序迁移到处理UTF-8的问题。
原因:
1. 在PCRE正则表达式中,需要添加utf8标志,以便将模式解释为实际的字符而不是字节。
2. 应使用Unicode字符类代替标准Perl字符类,以确保正则表达式对非拉丁字母正确。
解决方法:
1. 在PCRE正则表达式中添加utf8标志。
2. 使用Unicode字符类替代标准Perl字符类。
3. 替换一些函数为多字节版本。
4. 在MySQL配置文件中设置字符集和排序规则。
5. 在PHP ini文件中设置mb_internal_encoding,并设置其他推荐参数。
6. 在表单中设置accept-charset为UTF-8,以告诉浏览器以UTF-8提交表单。
7. 在表单中添加隐藏字段,以防止一些浏览器以其他编码方式提交表单。
8. 在Apache配置文件中设置"AddDefaultCharset utf-8"。
9. 在HTTP头部设置meta content-type。
文章如下:
将一个php应用程序迁移到处理UTF-8的问题
在将php应用程序迁移到处理UTF-8的过程中,有一些需要注意的事项。除了简单地替换函数外,还需要对正则表达式和数据库进行特殊处理。
正则表达式是处理字符串的重要工具之一。在处理可能包含非ASCII字符的字符串时,需要添加utf8标志,以确保模式被解释为实际字符而不是字节。例如,可以使用以下代码添加utf8标志:
$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字符类替代标准Perl字符类,以确保正则表达式对非拉丁字母正确。例如,可以使用`\p{L}`替代`\w`表示任何“字母”字符,使用`\p{Z}`替代`\s`表示任何“空格”字符,使用`\p{N}`替代`\d`表示任何“数字”字符。
在函数方面,需要替换一些函数为多字节版本。以下是一些需要替换的函数及其替代函数:
$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时,需要注意设置正确的字符集和排序规则。设置字符集为`utf8mb4`,排序规则为`utf8mb4_unicode_ci`。这样可以支持包括4字节编码字符在内的所有UTF-8字符。具体设置如下:
[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
此外,在PHP ini文件中设置`mb_internal_encoding`为`UTF-8`,并设置其他推荐参数,如下所示:
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
为了确保浏览器正确选择UTF-8编码的表单提交,需要在表单中设置`accept-charset`为UTF-8,并在表单中添加隐藏字段,以防止某些浏览器以其他编码方式提交表单。
除了上述内容,还有一些其他细节需要注意,如在Apache配置文件中设置`AddDefaultCharset utf-8`,在HTTP头部设置meta content-type等。
通过按照以上方法处理不同的问题,可以成功将php应用程序迁移到处理UTF-8编码,从而避免处理不同字符集所带来的麻烦。