通过php存储特殊字符(德语)SqlServer

时间:2012-09-14 13:43:23

标签: php sql-server encoding utf-8 pdo

我有一台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处理mssql时的默认编码类型是UTF-8

新发展:

一位同事向我指出了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编码时会有效?

2 个答案:

答案 0 :(得分:2)

数据库可以处理特殊字符,甚至不支持Unicode集(UTF-8恰好是编码,特别是可变长度编码)。

字符集是数字和字符之间的映射。 Unicode和ASCII是字符集的常见示例。 Unicode声明符号映射到数字8364(实际上它使用代码点 U + 20AC)。 UTF-8是一种编码 Unicode代码点的方法,用三个字节代表U+20AC0xE2 0x82 0xAC; UTF-16是Unicode代码点的另一种编码,它始终使用两个字节:0x20AClink)。这两种编码都引用了Unicode目录中相同的第8364条。

ASCII既是字符集又是编码方案:ASCII字符集映射从0到127到128 人类字符的数字,ASCII编码需要一个字节。

永远记住String是一个人类概念。它由元组(byte_content, encoding)在计算机中表示。假设您要在数据库中存储Unicode字符串。 请注意:如果您只需要支持德国用户,则无需使用Unicode集。当您想要在同一列中同时存储阿拉伯语,中文,希伯来语和德语时,它非常有用。 MS SQLServer使用UCS-2对Unicode进行编码,这适用于声明为NCHARNVARCHAR的列(请注意N前缀)。因此,您的第一个操作是检查目标列类型是否实际为nvarchar(或nchar)。

然后,假设您的PHP脚本中的所有输入字符串都是UTF-8编码的。你想执行像

这样的事情
$stmt->bindParam(':text', $utf8_encoded_text);

根据the documentation,UTF-8是默认的字符串编码。我希望与NVARCHAR合作足够聪明,否则您可能需要使用the extra options

您同事的解决方案不存储 Unicode字符串:它在ISO-8859-1空间中转换,然后将字节保存在简单 CHARVARCHAR列。区别在于您将无法在ISO-8859-1空间之外存储字符(例如波兰语)

答案 1 :(得分:0)

查看this article关于“在Web应用程序中处理Unicode前后”。到目前为止,我在这个主题上看过的最好的文章之一。如果您遵循指南并且问题仍然存在,那么您肯定知道这不是您的错。