PHP和MySQL中使用国际字符串的最佳实践

PHP和MySQL中使用国际字符串的最佳实践,php,mysql,internationalization,Php,Mysql,Internationalization,经常会发生这样的情况:字符如é被转换为Ã),即使MySQL数据库、表和字段的排序规则设置为utf8_general_ci。页面内容类型中的编码也设置为UTF8 我知道utf8_编码/解码,但我不太确定在哪里以及如何使用它 我已经阅读了“”文章,但我需要一些MySQL/PHP特定的指针 问题:如何确保用户输入的包含国际字符的数据不会被破坏?第一次查看时,我认为缺少一件重要的事情(也许我忽略了这一点)。 根据您的MySQL安装和/或配置,您必须设置连接编码,以便MySQL知道您希望在客户端使用的编码

经常会发生这样的情况:字符如é被转换为Ã),即使MySQL数据库、表和字段的排序规则设置为utf8_general_ci。页面内容类型中的编码也设置为UTF8

我知道utf8_编码/解码,但我不太确定在哪里以及如何使用它

我已经阅读了“”文章,但我需要一些MySQL/PHP特定的指针

问题:如何确保用户输入的包含国际字符的数据不会被破坏?

第一次查看时,我认为缺少一件重要的事情(也许我忽略了这一点)。 根据您的MySQL安装和/或配置,您必须设置连接编码,以便MySQL知道您希望在客户端使用的编码(即MySQL连接的客户端,应该是您的PHP脚本)。您可以通过手动发出

SET NAMES utf8
在向MySQL服务器发送任何其他查询之前进行查询

如果您在PHP端使用PDO,您可以使用

$db=new PDO($dsn, $user, $pass);
$db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");

初始化数据库连接时。

为了提高unicode的正确性,应该使用utf8\u unicode\u ci(尽管文档中对差异的描述有点模糊)。您还应该确保以下Mysql标志设置正确-

  • 默认字符集=utf8
  • 跳过字符集客户端握手//重要,这样客户端就不会强制执行其他编码
可以在mysql配置文件中(在[mysqld]选项卡下)或在运行时通过发送适当的查询进行设置。

您应该做的事情:

  • 确保Apache发布UTF-8内容。在httpd.conf中执行此操作,或者使用PHP的
    header()
    -函数手动执行此操作
  • 确保您的数据库连接是UTF8<代码>设置名称utf8起作用
  • 确保所有表格都设置为UTF8
  • 如果您在PHP和模板文件中存储国际字符,请确保它们都编码为UTF8

执行此操作时,通常不需要使用
mb_字符串
utf8_编码/解码
-函数进行太多操作。

排序规则和字符集不是一回事。您的排序规则需要与字符集匹配,因此,如果您的字符集是utf-8,那么排序规则也应该匹配。但是,选择错误的排序规则不会使您的数据混乱,只需使字符串比较/排序工作错误即可

也就是说,有几个地方可以在PHP中设置字符集设置。如果可能的话,我建议您全程使用utf-8。需要指定字符集的位置包括:

  • 数据库。这可以在数据库、表和字段级别上设置,甚至可以在每个查询级别上设置
  • PHP和数据库之间的连接
  • HTTP输出;确保HTTP头
    内容类型
    指定utf-8。您可以在PHP和Apache中设置默认值,也可以使用PHP的函数
  • HTTP输入。通常情况下,表单提交时使用的字符集与在中提供页面时使用的字符集相同,但为了确保这一点,您应该指定属性。还要确保URL是utf-8编码的,或者避免在URL中使用非ascii字符(和GET参数)
/解码函数的名称有点奇怪。它们专门在拉丁文1(ISO-8859-1)和utf-8之间转换。如果应用程序中的所有内容都是utf-8,那么就不需要经常使用它们

关于utf-8和PHP至少有两个问题。首先,PHP的内置字符串函数希望字符串是单字节的。对于很多操作来说,这并不重要,但这意味着你不能依赖其他功能。目前有很多限制。通常情况下,这不是一个大问题,但特别是在使用三方库时,您需要意识到事情可能会因此而爆炸。一种选择是使用mb_字符串扩展,它可以选择用支持utf-8的替代方案替换所有麻烦的函数。它仍然不是一个100%防弹的解决方案,但它在大多数情况下都有效


另一个问题是,PHP的某些安装仍然启用了该设置。这个问题与utf-8是正交的,但可能会导致一些头痛。为了您自己的理智,请将其关闭。

无论使用何种语言编写,如果您要创建一个允许多种编码的应用程序,请将其分块处理:

  • 识别编码
      不知何故,你想知道你正在处理什么样的编码,否则,进一步考虑它是没有意义的。你最终会得到垃圾车
  • 处理你的字节
    • 把这些字符串想象成不是字符的“字符串”,而是字节列表
    • PHP特别狡猾。不要让它在运行中截断您的数据。如果要重新设置UTF-8字符串,请确保将其标识为UTF-8字符串
  • 液晶显示器的存储
    • 同样,您不希望截断数据。如果你用英语存储一个句子,你能同时存储一组汉语字形吗?阿拉伯语怎么样?以下哪项需要的空间最多?解释一下

评论中的某个地方提到了这一点,但确实很难错过!对于任何刚刚阅读本文的人(截至2010年3月),现在可以在