PHP 与 UTF-8

没有一行式解决方案。当心、注意细节,以及一致性。

PHP 中的 UTF-8 糟透了。原谅个人用词。php

目前 PHP 在低层次上还不支持 Unicode。有几种方式能够确保 UTF-8 字符串可以被正确处理, 但并不容易,须要深刻到 web 应用的全部层面,从 HTML,到 SQL,到 PHP。咱们旨在提供一个简洁、 实用的概述。html

PHP 层面的 UTF-8

基本的字符串操做,如串接 两个字符串、将字符串赋给变量,并不须要任何针对 UTF-8 的特殊东西。 然而,多数 字符串函数,如 strpos()strlen,就须要特殊的考虑。 这些函数都有一个对应的 mb_* 函数:例如,mb_strpos()mb_strlen()。 这些对应的函数统称为多字节字符串函数。 这些多字节字符串函数是专门为操做 Unicode 字符串而设计的。java

当你操做 Unicode 字符串时,必须使用 mb_* 函数。 例如,若是你使用 substr() 操做一个 UTF-8 字符串,其结果就极可能包含一些乱码。 正确的函数应该是对应的多字节函数, mb_substr()mysql

难的是始终记得使用 mb_* 函数。即便你仅一次忘了,你的 Unicode 字符串在接下来的处理中就可能产生乱码。git

并非全部的字符串函数都有一个对应的 mb_*。若是不存在你想要的那一个,那你就只能自认倒霉了。web

此外,在每一个 PHP 脚本的顶部(或者在全局包含脚本的顶部)你都应使用 mb_internal_encoding 函数,若是你的脚本会输出到浏览器,那么还得紧跟其后加个mb_http_output() 函数。在每一个脚本中显式地定义字符串的编码在之后能为你减小不少使人头疼的事情。sql

最后,许多操做字符串的 PHP 函数都有一个可选参数让你指定字符编码。 如有该选项, 你应始终显式地指明 UTF-8 编码。 例如,htmlentities() 就有一个字符编码方式选项,在处理这样的字符串时应始终指定 UTF-8。数据库

MySQL 层面的 UTF-8

若是你的 PHP 脚本会访问 MySQL,即便你听从了前述的注意事项,你的字符串也有可能在数据库中存储为非 UTF-8 字符串。浏览器

确保从 PHP 到 MySQL 的字符串为 UTF-8 编码的,确保你的数据库以及数据表均设置为 utf8mb4 字符集, 而且在你的数据库中执行任何其余查询以前先执行 MySQL 查询 `set names utf8mb4`。这是相当重要的。 示例请查看链接并查询 MySQL 数据库一节内容。函数

注意你必须使用 `utf8mb4` 字符集来得到完整的 UTF-8 支持,而不是 `utf8` 字符集!缘由请查看进一步阅读

浏览器层面的 UTF-8

使用 mb_http_output() 函数 来确保你的 PHP 脚本输出 UTF-8 字符串到浏览器。 而且在 HTML 页面的 <head> 标签块中包含 字符集 <meta> 标签块

示例

<?php
// Tell PHP that we're using UTF-8 strings until the end of the script
mb_internal_encoding('UTF-8');

// Tell PHP that we'll be outputting UTF-8 to the browser
mb_http_output('UTF-8');

// Our UTF-8 test string
$string = 'Aš galiu valgyti stiklą ir jis manęs nežeidžia';

// Transform the string in some way with a multibyte function
$string = mb_substr($string, 0, 10);

// Connect to a database to store the transformed string
// See the PDO example in this document for more information
// Note the `set names utf8mb4` commmand!
$link = new \PDO(   'mysql:host=your-hostname;dbname=your-db',
                    'your-username',
                    'your-password',
                    array(
                        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                        \PDO::ATTR_PERSISTENT => false,
                        \PDO::MYSQL_ATTR_INIT_COMMAND => 'set names utf8mb4'
                    )
                );

// Store our transformed string as UTF-8 in our database
// Assume our DB and tables are in the utf8mb4 character set and collation
$handle = $link->prepare('insert into Sentences (Id, Body) values (?, ?)');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->bindValue(2, $string);
$handle->execute();

// Retrieve the string we just stored to prove it was stored correctly
$handle = $link->prepare('select * from Sentences where Id = ?');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->execute();

// Store the result into an object that we'll output later in our HTML
$result = $handle->fetchAll(\PDO::FETCH_OBJ);
?><!doctype html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>UTF-8 test page</title>
    </head>
    <body>
        <?php
        foreach($result as $row){
            print($row->Body);  // This should correctly output our transformed UTF-8 string to the browser
        }
        ?>
    </body>
</html>

 

进一步阅读

相关文章
相关标签/搜索