UTF-8 一路走来

2022-08-30 05:45:22

我正在设置一个新服务器,并希望在我的Web应用程序中完全支持UTF-8。我过去曾在现有服务器上尝试过此操作,并且似乎总是最终不得不回退到ISO-8859-1。

我究竟需要在哪里设置编码/字符集?我知道我需要配置Apache,MySQL和PHP来做到这一点 - 是否有一些我可以遵循的标准清单,或者可能排除不匹配发生的地方?

这是针对新的Linux服务器,运行MySQL 5,PHP,5和Apache 2。


答案 1

数据存储

  • 指定数据库中所有表和文本列的字符集。这使得MySQL以物理方式存储和检索以UTF-8本机编码的值。请注意,如果指定了排序规则(没有任何显式字符集),MySQL将隐式使用编码。utf8mb4utf8mb4utf8mb4_*

  • 在较旧版本的MySQL(<5.5.3)中,不幸的是,您将被迫简单地使用,它仅支持Unicode字符的子集。我希望我是在开玩笑。utf8

数据访问

  • 在应用程序代码(例如.PHP)中,无论使用哪种数据库访问方法,都需要将连接字符集设置为 。这样,MySQL在将数据移交给应用程序时,不会从其本机UTF-8进行转换,反之亦然。utf8mb4

  • 一些驱动程序提供了自己的机制来配置连接字符集,该机制既更新了自己的内部状态,又通知MySQL要在连接上使用的编码 - 这通常是首选方法。在 PHP 中:

    • 如果将 PDO 抽象层与 PHP ≥ 5.3.6 一起使用,则可以在 DSN 中指定:charset

       $dbh = new PDO('mysql:charset=utf8mb4');
      
    • 如果您使用的是 mysqli,则可以调用 set_charset()

        $mysqli->set_charset('utf8mb4');       // object oriented style
        mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • 如果您坚持使用普通的mysql,但碰巧≥5.2.3运行PHP,则可以调用mysql_set_charset

  • 如果驱动程序没有提供自己的机制来设置连接字符集,则可能必须发出查询以告知MySQL应用程序期望连接上的数据如何编码:设置名称'utf8mb4'

  • 关于 /的考虑与上述相同。utf8mb4utf8

输出

  • 应在 HTTP 标头中设置 UTF-8,例如 .您可以通过在php中设置default_charset.ini(首选)或使用函数手动实现。Content-Type: text/html; charset=utf-8header()
  • 如果应用程序将文本传输到其他系统,则还需要通知它们字符编码。对于 Web 应用程序,必须告知浏览器发送数据的编码(通过 HTTP 响应标头或 HTML 元数据)。
  • 使用 对输出进行编码时,添加为第二个参数。json_encode()JSON_UNESCAPED_UNICODE

输入

  • 浏览器将以为文档指定的字符集提交数据,因此无需对输入执行任何特别操作。
  • 如果您对请求编码有疑问(以防它可能被篡改),您可以在尝试存储或将其用于任何地方之前,将每个收到的字符串验证为有效的UTF-8。PHP的mb_check_encoding()可以解决问题,但你必须虔诚地使用它。这真的没有办法解决这个问题,因为恶意客户端可以用他们想要的任何编码提交数据,我还没有找到让PHP可靠地为你做到这一点的技巧。

其他代码注意事项

  • 显然,您将要提供的所有文件(PHP,HTML,JavaScript等)都应该用有效的UTF-8编码。

  • 您需要确保每次处理 UTF-8 字符串时,您都可以安全地执行此操作。不幸的是,这是困难的部分。您可能希望广泛使用PHP的mbstring扩展。

  • PHP 的内置字符串操作在默认情况下不是 UTF-8 安全的。使用普通的PHP字符串操作可以安全地执行一些事情(例如串联),但是对于大多数事情,您应该使用等效的函数。mbstring

  • 要知道你在做什么(请阅读:不要搞砸),你真的需要知道UTF-8以及它在尽可能低的水平上是如何工作的。查看 utf8.com 中的任何链接,以获取一些很好的资源来学习您需要了解的所有内容。


答案 2

我想为chazomaticus的出色答案添加一件事:

不要忘记META标签(就像这样,或者它的HTML4或XHTML版本):

<meta charset="utf-8">

这似乎微不足道,但IE7之前给我带来了问题。

我做对了一切;数据库,数据库连接和内容类型HTTP标头都设置为UTF-8,并且在所有其他浏览器中都可以正常工作,但Internet Explorer仍然坚持使用“西欧”编码。

事实证明,该页面缺少META标记。添加它解决了问题。

编辑:

W3C实际上有一个相当大的部分专门用于I18N。他们有很多与这个问题相关的文章 - 描述了HTTP,(X)HTML和CSS方面的事情:

他们建议同时使用HTTP标头和HTML元标记(或在XHTML作为XML的情况下使用XML声明)。


推荐