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来存储字符,因 ...
随机推荐
- Effective C++笔记03:资源管理
资源:动态分配的内存.文件描写叙述器.相互排斥锁.图形界面中的字型与笔刷.数据库连接以及网络sockets等,不管哪一种资源,重要的是,当你不再使用它时,必须将它还给系统. 条款13:以对象管理资源 ...
- 接口处理篇 accept bind connect atan2 htons inet_addr inet_aton inet_ntoa listen ntohl recv send sendto socket
accept(接受socket连线) 相关函数 socket,bind,listen,connect 表头文件 #include<sys/types.h> #include<sys/ ...
- 版本号控制-git(二)
上次文章给大家介绍了Git的一些基本知识(http://www.cnblogs.com/jerehedu/p/4582398.html).并介绍了使用git init初始化化版本号库.使用git ad ...
- utf-8-validation
https://leetcode.com/problems/utf-8-validation/ public class Solution { public boolean validUtf8(int ...
- 第十七章 springboot + devtools(热部署)
技术介绍 devtools:是boot的一个热部署工具,当我们修改了classpath下的文件(包括类文件.属性文件.页面等)时,会重新启动应用(由于其采用的双类加载器机制,这个启动会非常快,如果发现 ...
- python3 使用openpyxl库读写excel(续)
官网:https://openpyxl.readthedocs.io/en/stable/
- Nginx配置文件(nginx.conf)配置具体解释
欢迎扫码增加Java高知群交流 Nginx的配置文件nginx.conf配置具体解释例如以下: user nginx nginx ; Nginx用户及组:用户 组. window下不指定 wo ...
- CentOS 7 中 hostnamectl 的使用
hostnamectl 是在 centos7 中新增加的命令,它是用来修改主机名称的,centos7 修改主机名称会比以往容易许多. 用法 # hostnamectl -h -h --help 显示帮 ...
- What's the difference between - (one hyphen) and — (two hyphens) in a command?
bash中看到这样的命令, curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - sudo apt-get install - ...
- C++中无法解析的外部符号错误
在编译C++程序的时候,如果引用了对应的头文件,但是调用一个函数的时候仍然出现" 无法解析的外部符号错误"的编译错误,比如: 无法解析的外部符号__imp__PathFileE ...