19

即使 MySQL 数据库、表和字段的排序规则设置为 utf8_general_ci ,经常会发生诸如é之类的字符转换为é的情况。页面的Content-Type中的编码也设置为 UTF8。

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

我已阅读“每个软件开发人员绝对、肯定必须了解 Unicode 和字符集(没有借口!) ”文章,但我需要一些 MySQL / PHP 特定的指针。

如何确保用户输入的包含国际字符的数据不会损坏?

4

5 回答 5

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");

初始化数据库连接时。

于 2008-09-26T18:01:31.050 回答
8

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

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

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

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

关于 utf-8 和 PHP,至少有两个陷阱。首先是 PHP 的内置字符串函数期望字符串是单字节的。对于很多操作来说,这无关紧要,但它意味着你不能依赖strlen其他功能。在这个页面上有一个很好的限制。通常,这不是什么大问题,但特别是在使用 3 方库时,您需要注意这可能会导致问题。一种选择是使用 mb_string 扩展,它可以选择用 utf-8 感知的替代方案替换所有麻烦的函数。它仍然不是 100% 防弹的解决方案,但它适用于大多数情况。

另一个问题是 PHP 的某些安装仍然magic_quotes打开了该设置。这个问题与 utf-8 正交,但可能会导致一些头疼。关掉它,为了你自己的理智。

于 2008-09-27T13:13:13.480 回答
2

你应该做的事情:

  • 确保 Apache 输出 UTF-8 内容。在您的 httpd.conf 中执行此操作,或使用 PHP 的header()-function 手动执行此操作。
  • 确保您的数据库连接是 UTF8。SET NAMES utf8成功了。
  • 确保所有表都设置为 UTF8。
  • 如果您在其中存储国际字符,请确保所有 PHP 和模板文件都被编码为 UTF8。

执行此操作时,您通常不必使用mb_stringor函数做太多utf8_encode/decode事情。

于 2008-09-27T12:37:39.167 回答
0

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

  • 默认字符集=utf8
  • skip-character-set-client-handshake //重要的是客户端不会强制执行另一种编码

这些可以在 mysql 配置文件(在 [mysqld] 选项卡下)或在运行时通过发送适当的查询来设置。

于 2008-09-26T18:04:57.157 回答
0

不管它是用什么语言编写的,如果您要创建一个允许多种编码的应用程序,请分段处理:

  • 识别编码
    • 不知何故,您想找出您正在处理的编码类型,否则,进一步考虑它是毫无意义的。你最终会得到垃圾字符。
  • 处理你的字节
    • 认为这些字符串不太像字符的“字符串”,而更像是字节列表
    • PHP 尤其狡猾。不要让它即时截断您的数据。如果您正在对 UTF-8 字符串进行正则表达式,请确保将其标识为这样
  • 液晶显示器
    • Again, you don't want to truncate data. If you're storing a sentence in English, can you also store a set of Mandarin glyphps? How about Arabic? Which of these is going to require the most space? Account for it.
于 2008-09-27T19:30:38.957 回答