我有一台Fedora机器充当服务器,apache运行php 5.3
脚本充当各种来源的输入页面,向我发送“消息”。
php脚本调用如:serverAddress/phpScript.php?message=MyMessage
然后通过PDO保存消息以连接到SqlServer 2008 db。
如果消息包含任何特殊字符(例如德语),例如:üäöß然后在数据库中我会得到一些乱码而不是正确的字符串:üößÃ
db完全能够支持UTF-8 - 我可以连接并发送/检索德语字符而不会出现任何其他工具(不是通过php)的问题。
在php脚本中:
导致此行为的原因是什么?我该如何解决?
启用了多字节(yum install php-mbstring,然后重启apache)
在我的php脚本开头我有:
mb_internal_encoding('UTF-8'); mb_http_output('UTF-8'); mb_http_input('UTF-8'); mb_language('uni'); mb_regex_encoding('UTF-8'); ob_start('mb_output_handler');
新发展:
一位同事向我指出了PDO_DBLIB page(此时只能从缓存中看到),我看到$res->bindValue(':value', iconv('UTF-8', 'ISO8859-1', $value);
我将所有$res->bindParam(':text',$text);
替换为$res->bindParam(':text',iconv('UTF-8', 'ISO8859-1',$text));
,一切正常:)
不再需要mb_internal_encoding ....和所有其他行。
为什么使用ISO8859-1编码时会有效?
答案 0 :(得分:2)
数据库可以处理特殊字符,甚至不支持Unicode集(UTF-8恰好是编码,特别是可变长度编码)。
字符集是数字和字符之间的映射。 Unicode和ASCII是字符集的常见示例。 Unicode声明符号€
映射到数字8364
(实际上它使用代码点 U + 20AC)。 UTF-8是一种编码 Unicode代码点的方法,用三个字节代表U+20AC
:0xE2
0x82
0xAC
; UTF-16是Unicode代码点的另一种编码,它始终使用两个字节:0x20AC
(link)。这两种编码都引用了Unicode目录中相同的第8364条。
ASCII既是字符集又是编码方案:ASCII字符集映射从0到127到128 人类字符的数字,ASCII编码需要一个字节。
永远记住String是一个人类概念。它由元组(byte_content, encoding)
在计算机中表示。假设您要在数据库中存储Unicode字符串。 请注意:如果您只需要支持德国用户,则无需使用Unicode集。当您想要在同一列中同时存储阿拉伯语,中文,希伯来语和德语时,它非常有用。 MS SQLServer使用UCS-2对Unicode进行编码,这适用于声明为NCHAR
或NVARCHAR
的列(请注意N
前缀)。因此,您的第一个操作是检查目标列类型是否实际为nvarchar
(或nchar
)。
然后,假设您的PHP脚本中的所有输入字符串都是UTF-8编码的。你想执行像
这样的事情$stmt->bindParam(':text', $utf8_encoded_text);
根据the documentation,UTF-8是默认的字符串编码。我希望与NVARCHAR
合作足够聪明,否则您可能需要使用the extra options。
您同事的解决方案不存储 Unicode字符串:它在ISO-8859-1空间中转换,然后将字节保存在简单 CHAR
或VARCHAR
列。区别在于您将无法在ISO-8859-1空间之外存储字符(例如波兰语)
答案 1 :(得分:0)
查看this article关于“在Web应用程序中处理Unicode前后”。到目前为止,我在这个主题上看过的最好的文章之一。如果您遵循指南并且问题仍然存在,那么您肯定知道这不是您的错。