本篇博文主要讲述编码类文件Utf8.php。UTF8类的主要功能是检测CI框架和环境是否支持Utf8编码,转换编码,过滤字符串的功能。这个功能不多,逻辑也不是特别麻烦,下面我们就一步一步的来解析这个文件。
1、构造函数__construct()
/** * 构造函数:检测是否支持utf8 */ public function __construct() { if (defined('PREG_BAD_UTF8_ERROR') && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) && strtoupper(config_item('charset')) === 'UTF-8') { define('UTF8_ENABLED', TRUE); log_message('debug', 'UTF-8 Support Enabled'); } else { define('UTF8_ENABLED', FALSE); log_message('debug', 'UTF-8 Support Disabled'); } log_message('info', 'Utf8 Class Initialized'); }
此函数的功能首先判断如果正则表达式支持utf8,iconv库已经安装,多字节字符串函数重载没有启用,应用程序字符集是utf8,那么定义常量UTF8_ENABLED 值为 true,记录日志:UTF-8 Support Enabled。否则判断如果正则表达式不支持utf8或者iconv库没有安装或者多字节字符串函数重载已经启用或者应用程序字符集不是utf8,那么设置常量UTF8_ENABLED 为false,记录日志:UTF-8 Support Disabled。最后记录日志信息 Utf8 Class Initialized。
2、清理utf8编码的字符串 clean_string()
/** * 过滤UTF8字符串,因为编码转换成功率不会到100% */ public function clean_string($str) { if ($this->is_ascii($str) === FALSE) { if (MB_ENABLED) { $str = mb_convert_encoding($str, 'UTF-8', 'UTF-8'); } elseif (ICONV_ENABLED) { $str = @iconv('UTF-8', 'UTF-8//IGNORE', $str); } } return $str; }
函数首先判断如果字符串不是ASCII码,使用iconv函数将字符串转码(关于iconv函数详情见http://www.php.net/manual/zh/function.iconv.php)。IGNORE表示如果字符串不被转换为UTF-8,则已相近的字符串代替,否则字符串无法切割会产生E_NOTICE。
3、safe_ascii_for_xml()
public function safe_ascii_for_xml($str) { return remove_invisible_characters($str, FALSE); }
此函数删除所有在xml中可能导致问题的ASCII码字符,除了水平制表符,换行,回车。直接调用remove_invisible_characters()来删除无效的字符并返回。(注:remove_invisible_characters 函数在common.php中定义)。
4、convert_to_utf8()
public function convert_to_utf8($str, $encoding) { if (MB_ENABLED) { return mb_convert_encoding($str, 'UTF-8', $encoding); } elseif (ICONV_ENABLED) { return @iconv($encoding, 'UTF-8', $str); } return FALSE; }
convert_to_utf8()函数将字符串转换为utf8编码,首先如果mb_convert_encoding函数存在,使用mb_convert_encoding函数转换,否则如果iconv函数存在,使用iconv转换;如果上面两个函数都不存在则不能转换返回false;如果转换完成返回转换后的字符串。
5、is_ascii()
/** * 检测字符串是不是ASCII码 */ public function is_ascii($str) { return (preg_match('/[^\x00-\x7F]/S', $str) === 0); }
直接使用正则拼配返回测试结果。
最后,按照惯例,贴一下整个编码类Utf8.php文件的源码(注释版):
<?php /** * ======================================= * Created by Pocket Knife Technology. * User: ZhiHua_W * Date: 2016/10/20 0033 * Time: 上午 8:56 * Project: CodeIgniter框架—源码分析 * Power: Analysis for Utf8.php * ======================================= */ //不说 defined('BASEPATH') OR exit('No direct script access allowed'); //提供环境支持UTF-8 class CI_Utf8 { /** * 构造函数:检测是否支持utf8 * 日志记录 Utf8 Class Initialized */ public function __construct() { //对下列进行判断 //PCRE必须支持UTF-8 //iconv或mbstring必须安装 //应用必须是UTF-8字符集 if (defined('PREG_BAD_UTF8_ERROR') && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) && strtoupper(config_item('charset')) === 'UTF-8') { define('UTF8_ENABLED', TRUE); log_message('debug', 'UTF-8 Support Enabled'); } else { define('UTF8_ENABLED', FALSE); log_message('debug', 'UTF-8 Support Disabled'); } log_message('info', 'Utf8 Class Initialized'); } /** * 过滤UTF8字符串,因为编码转换成功率不会到100% */ public function clean_string($str) { //判断如果字符串不是ASCII码 if ($this->is_ascii($str) === FALSE) { if (MB_ENABLED) { $str = mb_convert_encoding($str, 'UTF-8', 'UTF-8'); } elseif (ICONV_ENABLED) { //IGNORE表示如果字符串不被转换为UTF-8,则已相近的字符串代替,否则字符串无法切割会产生E_NOTICE $str = @iconv('UTF-8', 'UTF-8//IGNORE', $str); } } //返回字符串 return $str; } /** * 去除字符串中不可见字符,以免造成xml解析错误 * 不包括换行,回车和水平制表符,利用common.php中remove_invisible_characters函数 */ public function safe_ascii_for_xml($str) { return remove_invisible_characters($str, FALSE); } /** * 将字符串转换为utf-8编码 */ public function convert_to_utf8($str, $encoding) { //如果mb_convert_encoding函数存在,使用mb_convert_encoding函数转换 if (MB_ENABLED) { return mb_convert_encoding($str, 'UTF-8', $encoding); } elseif (ICONV_ENABLED) { //如果iconv函数存在,使用iconv转换 return @iconv($encoding, 'UTF-8', $str); } //如果上面两个函数都不存在则不能转换返回false return FALSE; } /** * 检测字符串是不是ASCII码 */ public function is_ascii($str) { //使用正则拼配返回测试结果 return (preg_match('/[^\x00-\x7F]/S', $str) === 0); } }