我正在设置一个新的服务器,并希望在我的web应用程序中完全支持UTF-8。我过去曾在现有的服务器上尝试过这种方法,但似乎总是不得不回到ISO-8859-1。
我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来做到这一点-是否有一些标准的检查表,我可以遵循,或者排除哪里发生了不匹配?
这是一个新的Linux服务器,运行MySQL 5, PHP, 5和Apache 2。
我正在设置一个新的服务器,并希望在我的web应用程序中完全支持UTF-8。我过去曾在现有的服务器上尝试过这种方法,但似乎总是不得不回到ISO-8859-1。
我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来做到这一点-是否有一些标准的检查表,我可以遵循,或者排除哪里发生了不匹配?
这是一个新的Linux服务器,运行MySQL 5, PHP, 5和Apache 2。
当前回答
在我的例子中,我使用的是mb_split,它使用正则表达式。因此,我还必须手动确保正则表达式编码是UTF-8通过做mb_regex_encoding('UTF-8');
作为旁注,我还通过运行mb_internal_encoding()发现内部编码不是UTF-8,我通过运行mb_internal_encoding("UTF-8");来改变这一点。
其他回答
在PHP中,您需要使用多字节函数,或者打开mbstring.func_overload。这样,如果你的字符超过一个字节,像strlen这样的东西就可以工作。
你还需要确定你的回答的字符集。您可以像上面一样使用AddDefaultCharset,也可以编写返回标头的PHP代码。(或者你可以在你的HTML文档中添加一个META标签。)
除了在php.ini中设置default_charset外,你还可以在输出之前使用header()在你的代码中发送正确的字符集:
header('Content-Type: text/html; charset=utf-8');
在PHP中使用Unicode是很容易的,只要您认识到大多数字符串函数都不能使用Unicode,而且有些函数可能会完全破坏字符串。PHP认为“字符”长度为1字节。有时这是可以的(例如,explosion()只查找字节序列并将其用作分隔符——因此查找的实际字符并不重要)。但在其他时候,当函数实际设计为处理字符时,PHP并不知道您的文本中有Unicode中可以找到的多字节字符。
phputf8是一个很好的库。这将重写所有“坏”函数,因此您可以安全地处理UTF8字符串。也有像mb_string扩展这样的扩展试图为您做这件事,但我更喜欢使用库,因为它更可移植(但我写的是大众市场产品,所以这对我来说很重要)。但是phputf8可以在幕后使用mb_string来提高性能。
我最近发现,使用strtolower()可能会导致数据在特殊字符之后被截断的问题。
解决办法就是使用
mb_strtolower($string, 'UTF-8');
mb_使用MultiByte。它支持更多的字符,但总体来说有点慢。
数据存储:
在数据库中的所有表和文本列上指定utf8mb4字符集。这使得MySQL在物理上存储和检索原生UTF-8编码的值。注意,如果指定了utf8mb4_*排序规则(没有任何显式字符集),MySQL将隐式使用utf8mb4编码。 在MySQL的旧版本(< 5.5.3)中,不幸的是,您只能使用utf8,它只支持Unicode字符的一个子集。我希望我是在开玩笑。
数据访问:
在您的应用程序代码(例如PHP)中,无论您使用何种数据库访问方法,都需要将连接字符集设置为utf8mb4。通过这种方式,MySQL在将数据传递给应用程序时不会从其原生UTF-8进行转换,反之亦然。 一些驱动程序提供了自己的机制来配置连接字符集,它既更新自己的内部状态,又通知MySQL要在连接上使用的编码——这通常是首选的方法。在PHP中: 如果你使用PHP≥5.3.6的PDO抽象层,你可以在DSN中指定字符集: $dbh = new PDO('mysql:charset=utf8mb4'); 如果你正在使用mysqli,你可以调用set_charset(): mysqli - > set_charset(“utf8mb4”);//面向对象的样式 mysqli_set_charset(链接,美元“utf8mb4”);//程序风格 如果你只能使用普通的mysql,但碰巧运行的PHP≥5.2.3,你可以调用mysql_set_charset。 如果驱动程序没有提供自己的机制来设置连接字符集,你可能必须发出一个查询来告诉MySQL你的应用程序期望连接上的数据如何编码:set NAMES 'utf8mb4'。 对于utf8mb4/utf8,同样的考虑也适用于上面。
输出:
在HTTP报头中应该设置UTF-8,例如Content-Type: text/html;charset = utf - 8。你可以通过在php.ini中设置default_charset来实现(首选),或者手动使用header()函数。 如果您的应用程序将文本传输到其他系统,它们也需要被告知字符编码。对于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上的任何链接,获取一些好的资源,学习你需要知道的一切。
如果你想让MySQL服务器来决定字符集,而不是PHP作为客户端(旧行为;最好,在我看来),尝试添加skip-character-set-client-handshake到my.cnf,在[mysqld]下,并重新启动mysql。
如果您使用的不是UTF-8,这可能会带来麻烦。