Php UTF-8一路走来

Php UTF-8一路走来,php,mysql,linux,apache,utf-8,Php,Mysql,Linux,Apache,Utf 8,我正在设置一个新服务器,希望在我的web应用程序中完全支持UTF-8。我过去曾在现有服务器上尝试过这一点,但最终似乎不得不回到ISO-8859-1 我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来实现这一点——我是否可以遵循一些标准检查表,或者对出现不匹配的地方进行故障排除 这适用于运行MySQL 5、PHP、5和Apache 2的新Linux服务器。在PHP中,您需要使用或打开。这样,如果您的字符占用多个字节,则strlen之类的功能将起作用 您还需要确定响

我正在设置一个新服务器,希望在我的web应用程序中完全支持UTF-8。我过去曾在现有服务器上尝试过这一点,但最终似乎不得不回到ISO-8859-1

我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来实现这一点——我是否可以遵循一些标准检查表,或者对出现不匹配的地方进行故障排除


这适用于运行MySQL 5、PHP、5和Apache 2的新Linux服务器。

在PHP中,您需要使用或打开。这样,如果您的字符占用多个字节,则strlen之类的功能将起作用


您还需要确定响应的字符集。您可以如上所述使用AddDefaultCharset,也可以编写返回标头的PHP代码。(或者您可以向HTML文档添加元标记。)

除了在php.ini中设置
默认字符集
,您还可以在任何输出之前,使用
header()
从代码中发送正确的字符集:

header('Content-Type: text/html; charset=utf-8');
在PHP中使用Unicode很容易,只要您意识到大多数字符串函数不能使用Unicode,有些函数可能会完全损坏字符串。PHP认为“字符”的长度为1字节。有时这是可以的(例如,
explode()
只查找字节序列并将其用作分隔符,因此查找实际字符并不重要)。但在其他情况下,当函数实际设计用于处理字符时,PHP不知道文本具有Unicode中的多字节字符


一个好的借书室是。这将重写所有“坏”函数,以便您可以安全地处理UTF8字符串。也有像mbstring扩展这样的扩展尝试为您实现这一点,但我更喜欢使用库,因为它更便于移植(但我编写了大众市场产品,所以这对我很重要)。但是phputf8可以在幕后使用mbstring来提高性能。

数据存储

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

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

数据访问

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

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

    • 如果将抽象层与PHP一起使用≥ 5.3.6中,您可以指定
      字符集

    • 如果您正在使用,您可以拨打:

    • 如果您一直使用plain,但碰巧正在运行PHP≥ 5.2.3,你可以打电话

  • 如果驱动程序没有提供自己的机制来设置连接字符集,那么您可能必须发出一个查询,告诉MySQL您的应用程序希望如何对连接上的数据进行编码:

  • 关于
    utf8mb4
    /
    utf8
    的考虑同样适用于上述情况

输出

  • 如果您的应用程序将文本传输到其他系统,则还需要通知他们字符编码。对于web应用程序,必须通知浏览器发送数据的编码(通过HTTP响应头或电子邮件)

  • 在PHP中,您可以使用PHP.ini选项,或者自己手动发出
    内容类型
    MIME头,这只是更多的工作,但具有相同的效果

  • 使用
    json\u encode()
    对输出进行编码时,添加
    json\u UNESCAPED\u UNICODE
    作为第二个参数

输入

  • 不幸的是,在您尝试存储或在任何地方使用它之前,您应该验证每个接收到的字符串是否是有效的UTF-8。PHP可以做到这一点,但你必须虔诚地使用它。真的没有办法解决这个问题,因为恶意客户端可以以他们想要的任何编码提交数据,我还没有找到让PHP可靠地为您完成这项工作的窍门

  • 从我对当前的阅读来看,以下子项目符号对于现代HTML不再是必要的,甚至不再有效。我的理解是,浏览器将使用并提交文档指定字符集中的数据。但是,如果您针对的是较旧版本的HTML(XHTML、HTML4等),以下几点可能仍然有用:

    • 仅适用于HTML5之前的HTML:您希望浏览器发送给您的所有数据都是UTF-8格式。不幸的是,如果要可靠地执行此操作,唯一的方法是将
      接受字符集
      属性添加到所有
      标记中:
    • 仅适用于HTML5之前的HTML:请注意,W3C HTML规范规定,客户端“应该”默认使用服务器提供的任何字符集将表单发送回服务器,但这显然只是一个建议,因此需要在每个
      标记上显式显示
其他代码注意事项

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

  • 你需要做些什么
     $dbh = new PDO('mysql:charset=utf8mb4');
    
      $mysqli->set_charset('utf8mb4');       // object oriented style
      mysqli_set_charset($link, 'utf8mb4');  // procedural style
    
    <meta charset="utf-8">
    
    // storage
    // debian. apparently already utf-8
    
    // retrieval
    // the mysql database was stored in utf-8, 
    // but apparently php was requesting iso. this worked: 
    // ***notice "utf8", without dash, this is a mysql encoding***
    mysql_set_charset('utf8');
    
    // delivery
    // php.ini did not have a default charset, 
    // (it was commented out, shared host) and
    // no http encoding was specified in the apache headers.
    // this made apache send out a utf-8 header
    // (and perhaps made php actually send out utf-8)
    // ***notice "utf-8", with dash, this is a php encoding***
    ini_set('default_charset','utf-8');
    
    // submission
    // this worked in all major browsers once apache
    // was sending out the utf-8 header. i didnt add
    // the accept-charset attribute.
    
    // processing
    // changed a few commands in php, like substr,
    // to mb_substr
    
    $pdo = new PDO(
        'mysql:host=mysql.example.com;dbname=example_db',
        "username",
        "password",
        array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    
    mb_strtolower($string, 'UTF-8');
    
    if (!$mysqli->set_charset("utf8")) {
        printf("Error loading character set utf8: %s\n", $mysqli->error);
    } else {
       printf("Current character set: %s\n", $mysqli->character_set_name());
    }
    
    mysqli_set_charset($con,"utf8");