PHP 与 UTF-8 的最佳实践详细介绍


Posted in PHP onJanuary 04, 2017

《PHP中的字符串、编码、UTF-8》一文中描述了一些列的基础知识,比较枯燥,现在来说点有用的——PHP 字符串处理的最佳实践,本文是“PHP、字符串、编码、UTF-8”相关知识的第二部分。先说结论—— 在 PHP 中的各个方面使用 UTF-8 编码。

PHP 语言层面是不支持 Unicode字符集的,但是可以通过 UTF-8 编码能处理大部分问题。

最佳实践就是明确知道输入编码(不知道就检测),内部统一转换为 UTF-8 编码,输出编码也统一是 UTF-8编码。

PHP 层面如何处理 UTF-8

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

mbstring 扩展大部分的函数都需要基于一个编码(内部编码)来处理,请务必统一使用 UTF-8 编码,这个大部分可以在 PHP.INI 中配置。

从 PHP 5.6 开始,default_charset 配置可以替换 mbstring.http_input,mbstring.http_output 。

另外一个重要的配置就是 mbstring.language,这个默认值是 Neutral(UTF-8)。

注意文件编码和 mbstring 扩展的内部编码不是同一个概念。

概括的说来:

  • PHP.INI 中涉及到 mbstring 扩展的部分尽量使用 UTF-8。
  • 请用 mbstring 扩展函数代替原生字符串操作函数。
  • 在使用相关函数的时候,请务必了解你操作的字符的编码是什么,在使用对应函数的时候,显示的写上 UTF-8 编码参数,比如 htmlentities() 函数的第三个参数显示写上 UTF-8。

文件 IO 操作 如何处理 UTF-8

这里举个例子,假如你要打开一个文件,但是不知道文件内容是什么编码的,那么如何处理呢?

最佳实践就是,在打开的时候统一转换成 UTF-8,修改内容后就再转回原来的编码并保存到文件。看代码把:

if ( mb_internal_encoding()!="UTF-8") {
    mb_internal_encoding("UTF-8");
}

$file = "file.txt"; //一个编码为gbk的中文文件
$str= file_get_contents($file);
//不管来源是什么编码,统一显示的时候转换为 UTF-8
 if (mb_check_encoding($str,"GBK")) 
  $str = mb_convert_encoding($str,"UTF-8",“GBK”); 

$str ="修改内容";
$str = mb_convert_encoding($str,$srcbm,"UTF-8"); //原样转回去
file_put_contents($file,$str);

Mysql 和 UTF-8 的最佳实践

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

浏览器和 UTF-8 的最佳实践

这个也比较简单,就是你的输出内容假如是网页,那么你的字符串处理输出最总请保持为 UTF-8 ;同时 PHP.INI 中也明确设定 default_charset 为 UTF-8;HTML 的 Meta Tag 也明确标识为 UTF-8。

现在万事大吉了吗,并没有,虽然服务器和浏览器让用户使用 UTF-8 编码,但是用户的行为并没有约束性,他可能输入的是其他编码的字符,或者上传的文件名是其他编码的字符,那么怎么办呢?可以通过 mb_http_input() 和 mb_check_encoding() 函数来检测用户的编码,然后内部转换为 UTF-8。确保在任何一个层面,最终处理的是 UTF-8 编码。换句话说,需要手段能够知晓你的输入是什么编码的,处理完成后控制输出的编码是 UTF-8。

不建议使用 mbstring.encoding_translation 指令 和 mb_detect_encoding() 函数。折磨我半天。

操作系统和 UTF-8 的最佳实践

由于操作系统的原因,PHP 处理 Unicode 文件名的时候会有不同的处理机制。

在 Linux 中,文件名始终是 UTF-8 编码的,而在中文 Windows 环境下,文件名始终是 GBK 编码的,记住这一点就可以了。

通过例子说明下:

//命令行程序函数,运行在中文版 Windows 10 操作系统 ,文件编码为 UTF-8

function filenameexample() {
  $filename = "测试.txt" ;
  $gbk_filename = iconv("UTF-8","GBK",$filename);
  file_put_contents($gbk_filename, "测试");
  echo file_get_contents($gbk_filename);
}

function scandirexample() {
  $arr = scandir("./tmp");
  foreach ($arr as $v) {
    if ($v == "." || $v =="..")
      continue ;
    $filename = iconv( "GBK","UTF-8",$v ) ;
    $content = file_get_contents("./tmp/" . $v );
  }
}

假如不想写写兼容 Windows 和 linux 的程序,可以对文件名进行 urlencode 编码,比如:

function urlencodeexample() {
  $filename = "测试2.txt" ;
  $urlencodefilename = urlencode($filename) ;
  file_put_contents($urlencodefilename, "测试");
  echo file_get_contents($urlencodefilename);
 }

在用 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","附件.txt");
  header("Content-Disposition: attachment; filename=\"$filename\"");
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
php下一个阿拉伯数字转中文数字的函数
Jul 16 PHP
PHP is_dir() 判断给定文件名是否是一个目录
May 10 PHP
php设计模式 State (状态模式)
Jun 26 PHP
真正根据utf8编码的规律来进行截取字符串的函数(utf8版sub_str )
Oct 24 PHP
Yii2.0高级框架数据库增删改查的一些操作
Nov 16 PHP
PHP序列化/对象注入漏洞分析
Apr 18 PHP
Yii2中如何使用modal弹窗(基本使用)
May 30 PHP
既简单又安全的PHP验证码 附调用方法
Jun 02 PHP
php封装的smarty类完整实例
Oct 19 PHP
PHP实现mysqli批量执行多条语句的方法示例
Jul 22 PHP
php实现快速对二维数组某一列进行组装的方法小结
Dec 04 PHP
php判断IP地址是否在多个IP段内
Aug 18 PHP
详解Yii2 定制表单输入字段的标签和样式
Jan 04 #PHP
PHPExcel导出2003和2007的excel文档功能示例
Jan 04 #PHP
CI框架实现优化文件上传及多文件上传的方法
Jan 04 #PHP
PHP搭建大文件切割分块上传功能示例
Jan 04 #PHP
php实现的简单中文验证码功能示例
Jan 03 #PHP
php与c 实现按行读取文件实例代码
Jan 03 #PHP
浅谈PHP安全防护之Web攻击
Jan 03 #PHP
You might like
PHP简单系统数据添加以及数据删除模块源文件下载
2008/06/07 PHP
关于php fread()使用技巧
2010/01/22 PHP
PHP面向对象之旅:深入理解static变量与方法
2014/01/06 PHP
使用PHP和HTML5 FormData实现无刷新文件上传教程
2014/09/06 PHP
Laravel推荐使用的十个辅助函数
2019/05/10 PHP
图片完美缩放
2006/09/07 Javascript
firefox下jQuery UI Autocomplete 1.8.*中文输入修正方法
2012/09/19 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
2014/05/08 Javascript
c#+jquery实现获取radio和checkbox的值
2020/09/12 Javascript
JS运动基础框架实例分析
2015/03/03 Javascript
JS实现淡蓝色简洁竖向Tab点击切换效果
2015/10/06 Javascript
jquery实现简单实用的弹出层效果代码
2015/10/15 Javascript
javascript滚轮控制模拟滚动条
2016/10/19 Javascript
BootStrap实现响应式布局导航栏折叠隐藏效果(在小屏幕、手机屏幕浏览时自动折叠隐藏)
2016/11/30 Javascript
用npm-run实现自动化任务的方法示例
2019/01/14 Javascript
vue项目引入ts步骤(小结)
2019/10/31 Javascript
JS面向对象编程基础篇(三) 继承操作实例详解
2020/03/03 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
2020/03/12 Javascript
Javascript中Math.max和Math.max.apply的区别和用法详解
2020/08/24 Javascript
js观察者模式的弹幕案例
2020/11/23 Javascript
微信小程序 接入腾讯地图的两种写法
2021/01/12 Javascript
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
python中partial()基础用法说明
2018/12/30 Python
Python图像处理之颜色的定义与使用分析
2019/01/03 Python
Python multiprocessing多进程原理与应用示例
2019/02/28 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
用python画一只可爱的皮卡丘实例
2019/11/21 Python
详解Python中的路径问题
2020/09/02 Python
Html5内唤醒百度、高德APP的实现示例
2019/05/20 HTML / CSS
英国领先的奢侈品零售商之一:CRUISE
2016/12/02 全球购物
澳大利亚购买健身器材网站:Gym Direct
2019/12/19 全球购物
童装店创业计划书
2014/01/09 职场文书
学生会竞聘书范文
2014/03/31 职场文书
小学生自我评价100字(15篇)
2014/09/18 职场文书
2019最新版劳务派遣管理制度
2019/08/16 职场文书
js前端设计模式优化50%表单校验代码示例
2022/06/21 Javascript