PHP 与 UTF-8
没有一行式解决方案。小心、注意细节,以及一致性。
PHP 中的 UTF-8 糟透了。原谅我的用词。
目前 PHP 在低层次上还不支持 Unicode。有几种方式可以确保 UTF-8 字符串能够被正确处理, 但并不容易,需要深入到 web 应用的所有层面,从 HTML,到 SQL,到 PHP。我们旨在提供一个简洁、 实用的概述。
PHP 层面的 UTF-8
基本的字符串操作,如串接 两个字符串、将字符串赋给变量,并不需要任何针对 UTF-8 的特殊东西。 然而,多数 字符串函数,如 strpos() 和 strlen,就需要特殊的考虑。 这些函数都有一个对应的 mb_* 函数:例如,mb_strpos() 和 mb_strlen()。 这些对应的函数统称为多字节字符串函数。 这些多字节字符串函数是专门为操作 Unicode 字符串而设计的。
当你操作 Unicode 字符串时,必须使用 mb_* 函数。 例如,如果你使用 substr() 操作一个 UTF-8 字符串,其结果就很可能包含一些乱码。 正确的函数应该是对应的多字节函数, mb_substr()。
难的是始终记得使用 mb_* 函数。即使你仅一次忘了,你的 Unicode 字符串在接下来的处理中就可能产生乱码。
并不是所有的字符串函数都有一个对应的 mb_*。如果不存在你想要的那一个,那你就只能自认倒霉了。
此外,在每个 PHP 脚本的顶部(或者在全局包含脚本的顶部)你都应使用 mb_internal_encoding 函数,如果你的脚本会输出到浏览器,那么还得紧跟其后加个mb_http_output() 函数。在每个脚本中显式地定义字符串的编码在以后能为你减少很多令人头疼的事情。
最后,许多操作字符串的 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>
进一步阅读
- PHP 手册:多字节字符串函数
- PHP UTF-8 备忘单
- Stack Overflow: 什么因素致使 PHP 不兼容 Unicode?
- Stack Overflow: PHP 与 MySQL 之间国际化字符串的最佳实践
- 怎样在MySQL数据库中完整支持Unicode
PHP 与 UTF-8的更多相关文章
- 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念
转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...
- ascii、unicode、utf、gb等编码详解
很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称为"字节".再后来,他们又做了一些可以处理这 ...
- 转载:谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
转载: 谈谈Unicode编码,简要解释UCS.UTF.BMP.BOM等名词 这是一篇程序员写给程序员的趣味读物.所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级 ...
- Unicode 与 UTF 字符标准
Unicode 国际字符标准(UCS)是一个字符编码系统,它被设计用来支持世界各国不同语言书面文体之间的数据交换.处理以及显示. Unicode用两个字节表示一个字符.前127个字符与A ...
- 利用zxing制作彩色,高容错,支持中文等UTF编码的QR二维码图片
利用zxing制作彩色,高容错,支持中文等UTF编码的QR二维码图片.代码如下 import java.awt.Color;import java.io.File;import java.util.H ...
- UTF编码问题小结
在编程当中经常出现乱码的问题,而由此一般会引发很多惨剧,如读文件不成功.用户名显示乱码等,所以端午节抽了一小点时间好好看了一下编码问题,以备遗忘. 首先是中文编码,除了台湾和香港常用的BIG5,国内大 ...
- 请问什么是UTF字符串?
utf是编码方式,一般而言是国际性质的编码格式,有utf-8,utf-9,utf-16等多种形式,是最高级别的编码方式,也就是说如果你要读取的数据流设置成utf编码的话就要用到相应的编码方式来读取了, ...
- jsp中pageEncoding、charset=UTF -8
jsp中pageEncoding.charset=UTF -8" 在JSP/Servlet 中主要有以下几个地方可以设置编码,pageEncoding="UTF-8". ...
- java 乱码详解_jsp中pageEncoding、charset=UTF -8"、request.setCharacterEncoding("UTF-8")
http://blog.csdn.net/qinysong/article/details/1179480 java 乱码详解__jsp中pageEncoding.charset=UTF -8&quo ...
- Unicode(UTF&UCS)深度历险
Unicode(UTF&UCS)深度历险 计算机网络诞生后,大家慢慢地发现一个问题:一个字节放不下一个字符了!因为需要交流,本地化的文字需要能够被支持. 最初的字符集使用7bit来存储字符,因 ...
随机推荐
- 仿LOL项目开发第八天
仿LOL项目开发第八天 by 草帽 这节我们继续上节所讲的内容,上节我们初始化好了LoginWindow,当我们点击确认选择服务器按钮的时候,就发送服务器id给游戏服务器. 这里就开始涉及到客户端需要 ...
- 《Windows核心编程》第十一章——线程池
隐式使用工作项 #include <iostream> #include <windows.h> ; VOID NTAPI SimpleCallback(PTP_CALLBAC ...
- SHA加密算法工具类
1.利用Apache的工具类实现加密: maven: <dependency> <groupId>commons-codec</groupId> <artif ...
- Objective-C:字符串的反转Reverse
OC中字符串的反转方式可以用两种方式来处理: 第一种:从头到尾取出字符串的每一个字符,然后将其从尾到头添加到可变的字符串中,最后输出即可. 第二种:将OC内部的字符串转换为C语言中的字符串,然后动态分 ...
- go语言之进阶篇指针类型和普通类型的方法集
方法集 类型的方法集是指可以被该类型的值调用的所有方法的集合. 用实例实例 value 和 pointer 调用方法(含匿名字段)不受方法集约束,编译器编总是查找全部方法,并自动转换 receiver ...
- 【Handler】Looper 原理 详解 示例 总结
核心知识点 1.相关名词 UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue Handler:作用就是发送与处理信息, ...
- CentOS 7 开放防火墙端口命令
CentOS 7 开放防火墙端口 命令 最近公司新的server要求用CentOS7, 发现以前CentOS 6 系列中的 iptables 相关命令不能用了,查了下,发现Centos 7使用fire ...
- Golang 中三种读取文件发放性能对比
Golang 中读取文件大概有三种方法,分别为: 1. 通过原生态 io 包中的 read 方法进行读取 2. 通过 io/ioutil 包提供的 read 方法进行读取 3. 通过 bufio 包提 ...
- idea启动崩溃问题
idea启动崩溃问题 内存已经给到1024m了: 注意到项目比较大,有个参数ReservedCodeCasheSize,把这个修改为1024m, 学习了:https://www.cnblogs.com ...
- 红米NOTE应用闪退(包括系统设置等各种界面)问题解决经历
关机状态下同时按减音量按钮和开机按钮,进入一个菜单,选择recovery(减音量键是移动,加音量键是确定),当出现一个倒地的机器人的时候,稍待片刻按开机键会出现双清以及刷机菜单.wipe data/f ...