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

时间:2008-09-26 17:13:02

标签: php mysql internationalization

即使MySQL DB,表格和字段的排序规则设置为utf8_general_ci,也常常会将é等字符转换为é。页面的 Content-Type 中的编码也设置为UTF8。

我知道utf8_encode / decode,但我不太确定在何处以及如何使用它。

我已阅读“The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)”文章,但我需要一些MySQL / PHP特定的指针。

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

6 个答案:

答案 0 :(得分:14)

第一眼看http://www.nicknettleton.com/zine/php/php-utf-8-cheatsheet我认为缺少一件重要的事情(也许我忽略了这一点)。 根据您的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");
初始化数据库连接时

答案 1 :(得分:8)

整理和charset不是一回事。你的校对需要匹配字符集,所以如果你的字符集是utf-8,那么整理也是如此。选择错误的排序规则不会使您的数据混乱 - 只是错误地进行字符串比较/排序。

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

  • 数据库。这可以在数据库,表和字段级别设置,甚至可以在每个查询级别设置。
  • PHP和数据库之间的连接。
  • HTTP输出;确保HTTP标头Content-Type指定utf-8。您可以在PHP和Apache中设置默认值,也可以使用PHP的header函数。
  • HTTP输入。通常,表单将在提供页面的同一个字符集中提交,但为了确保,您应指定accept-charset属性。还要确保URL是utf-8编码的,或者避免在url(和GET参数)中使用非ascii字符。

utf8_encode / decode函数有点奇怪。它们专门在latin1(ISO-8859-1)和utf-8之间进行转换。如果您的应用程序中的所有内容都是utf-8,则不必使用它们。

关于utf-8和PHP至少有两个陷阱。首先,PHP的内置字符串函数希望字符串是单字节的。对于很多操作,这没关系,但它意味着你不能依赖strlen和其他功能。 this page的限制有很好的破坏。通常,这不是一个大问题,但特别是在使用三方库时,您需要意识到事情可能会爆炸。一个选项也是使用mb_string扩展,它可以选择用utf-8识别替代方法替换所有麻烦的函数。它仍然不是100%防弹解决方案,但它适用于大多数情况。

另一个问题是某些PHP安装仍然启用了magic_quotes设置。这个问题与utf-8正交,但可能导致一些头部刮伤。为了你自己的理智,把它关掉。

答案 2 :(得分:2)

答案 3 :(得分:2)

你应该做的事情:

  • 确保Apache发布UTF-8内容。在httpd.conf中执行此操作,或使用PHP的header() - 函数手动执行此操作。
  • 确保您的数据库连接是UTF8。 SET NAMES utf8可以解决问题。
  • 确保所有表格都设置为UTF8。
  • 如果您在其中存储国际字符,请确保所有PHP和模板文件都编码为UTF8。

执行此操作时,您通常无需使用mb_stringutf8_encode/decode - 函数。

答案 4 :(得分:0)

为了更好的unicode正确性,你应该使用utf8_unicode_ci(虽然文档对差异有点模糊)。您还应该确保正确设置了以下Mysql标志 -

  • 默认字符集= UTF8
  • skip-character-set-client-handshake //重要,因此客户端不会强制执行其他编码

可以在mysql配置文件(在[mysqld]选项卡下)或在运行时通过发送相应的查询来设置它们。

答案 5 :(得分:0)

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

  • 识别编码
    • 不知怎的,你想知道你正在处理什么样的编码,否则,进一步考虑它是没有意义的。你最终会得到垃圾字符。
  • 处理你的字节
    • 认为这些字符串不像字符串'字符串',更像是字节列表
    • PHP特别狡猾。不要让它在运行中截断您的数据。如果您要重新编写UTF-8字符串,请确保将其标识为
  • 存放液晶显示屏
    • 同样,您不想截断数据。如果你用英语存储一个句子,你还可以存储一套普通话吗?阿拉伯语怎么样?哪一个需要最大的空间?说明它。