PHP与UTF-8的那些事

当操作 Unicode 字符集的时候,使用相应的函数代替原生的字符串函数。举个例子,一个文件编码为 UTF-8 的 PHP 代码,假如使用 strlen() 函数是错误的,请使用 mb_strlen() 函数代替。

PHP处理UTF-8

PHP有mbstring扩展,自带几种字符串截取函数,其中常用到的就是 substr 和 mb_substr。

当操作 Unicode 字符集的时候,使用相应的函数代替原生的字符串函数。举个例子,一个文件编码为 UTF-8 的 PHP 代码,假如使用 strlen() 函数是错误的,请使用 mb_strlen() 函数代替。

如果你使用substr截取中文字符时会出现乱码,这是因为substr是按字节来截取的。即UTF-8编码的中文,使用substr截取,只会截取1/3个中文,当然出现乱码了。UTF-8编码时,一个汉字是3个字节。同样其他国家不同语言文字会产生多字节字符串问题,所以我们统统使用mb_strlen()来处理。

如果不清楚字符串的编码格式的话,可以用mb_detect_encoding检查。

如果要转换编码,使用函数iconv(),如GB2312  转UTF-8:

iconv("GB2312","UTF-8",$text);
知识兔

当遇到无法确定原编码是何种编码,或者iconv转化后无法正常显示时可用mb_convert_encoding 函数。

$str = mb_convert_encoding($str, "UTF-8");
知识兔

其实在php.ini中有个选项设置    default_charset = "UTF-8";,很多字符串处理函数如htmlentities()会使用这个默认字符集。

我们可以使用header()函数明确指定字符集,在PHP返回的响应中,Content-Type首部默认也使用这个值。

header("Content-Type: text/html;charset=utf-8");
知识兔

当然,我们在创建HTML文档的头部也应该加入这个mata标签:

<meta charset="UTF-8" />
知识兔

PHP浏览器下载文件名乱码

虽然我们将php代码、输出数据时都使用UTF-8,但是可能还会遇到很多诡异现象。比如,我遇到的坑,当要从服务器上下载一个文件时,IE浏览器、Edge在下载中文文件名时会乱码,还有当文件名包含空字符时,下载后的文件名称空格变成了+号等等这些诡异现象。

其实,PHP通过 header() 函数下载文件的时候,也要考虑浏览器和操作系统(大部分人使用的是 Windows),对于 Chrome 来说,输出的文件名编码可以是 UTF-8,Chrome 会自动将文件名转换为 GBK 编码。

而对于IE 来说,它继承了操作系统的环境,所以下载文件名假如是中文必须转码为 UTF-8 编码,否则下载的时候用户看到的是乱码文件名。 解决办法有了:

$agent=$_SERVER["HTTP_USER_AGENT"];if(strpos($agent,'MSIE')!==false ){
    $filename = iconv("UTF-8","GBK","中文附件.pdf");
    header("Content-Disposition: attachment; filename=\"$filename\"");
}
知识兔

PHP处理MySQL乱码

首先保证你的 Mysql 都是 UTF-8。然后 Mysql 客户端连接的时候也保持 UTF-8,具体到 PHP 中,就是 mysqli 或者 PDO 扩展连接 Mysql 的时候都设置 UTF-8 作为连接编码,两边保持一致,一般就不会遇到乱码问题。

例如使用PDO链接Mysql时,使用UTF-8字符集:

$pdo->query('SET NAMES utf8;');
知识兔

总结

1.处理多字节字符串时一定要知道数据的字符编码;

2.使用UTF-8字符编码存储数据;

3.使用UTF-8字符编码输出数据。

计算机