smarty中英文多编码字符截取乱码问题解决方法


Posted in PHP onOctober 28, 2014

本文实例讲述了smarty中英文多编码字符截取乱码问题解决方法,分享给大家供大家参考。具体方法如下:

一般网站页面的显示都不可避免的会涉及子字符串的截取,这个时候truncate就派上用场了,但是它只适合英文用户,对与中文用户来说,使用 truncate会出现乱码,而且对于中文英文混合串来说,截取同样个数的字符串,实际显示长度上却不同,视觉上会显得参差不齐,影响美观。这是因为一个中文的长度大致相当于两个英文的长度。此外,truncate也不能同时兼容GB2312, UTF-8等编码。
改良的smartTruncate: 文件名:modifier.smartTruncate.php
具体代码如下:

<?php 

function smartDetectUTF8($string) 

{ 

    static $result = array();

    if(! array_key_exists($key = md5($string), $result)) 

    { 

        $utf8 = " 

            /^(?: 

                [\x09\x0A\x0D\x20-\x7E]                            # ASCII 

                | [\xC2-\xDF][\x80-\xBF]                             # non-overlong 2-byte 

                | \xE0[\xA0-\xBF][\x80-\xBF]                       # excluding overlongs 

                | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}           # straight 3-byte 

                | \xED[\x80-\x9F][\x80-\xBF]                      # excluding surrogates 

                | \xF0[\x90-\xBF][\x80-\xBF]{2}                 # planes 1-3 

                | [\xF1-\xF3][\x80-\xBF]{3}                          # planes 4-15 

                | \xF4[\x80-\x8F][\x80-\xBF]{2}                  # plane 16 

            )+$/xs 

        ";

        $result[$key] = preg_match(trim($utf8), $string); 

    }

    return $result[$key]; 

}

function smartStrlen($string) 

{ 

    $result = 0;

    $number = smartDetectUTF8($string) ? 3 : 2;

    for($i = 0; $i < strlen($string); $i += $bytes) 

    { 

        $bytes = ord(substr($string, $i, 1)) > 127 ? $number : 1;

        $result += $bytes > 1 ? 1.0 : 0.5; 

    }

    return $result; 

}

function smartSubstr($string, $start, $length = null) 

{ 

    $result = '''';

    $number = smartDetectUTF8($string) ? 3 : 2;

    if($start < 0) 

    { 

        $start = max(smartStrlen($string) + $start, 0); 

    }

    for($i = 0; $i < strlen($string); $i += $bytes) 

    { 

        if($start <= 0) 

        { 

            break; 

        }

        $bytes = ord(substr($string, $i, 1)) > 127 ? $number : 1;

        $start -= $bytes > 1 ? 1.0 : 0.5; 

    }

    if(is_null($length)) 

    { 

        $result = substr($string, $i); 

    } 

    else 

    { 

        for($j = $i; $j < strlen($string); $j += $bytes) 

        { 

            if($length <= 0) 

            { 

                break; 

            }

            if(($bytes = ord(substr($string, $j, 1)) > 127 ? $number : 1) > 1) 

            { 

                if($length < 1.0) 

                { 

                    break; 

                }

                $result .= substr($string, $j, $bytes); 

                $length -= 1.0; 

            } 

            else 

            { 

                $result .= substr($string, $j, 1); 

                $length -= 0.5; 

            } 

        } 

    }

    return $result; 

}

function smarty_modifier_smartTruncate($string, $length = 80, $etc = ''...'', 

                                       $break_words = false, $middle = false) 

{ 

    if ($length == 0) 

        return '''';

    if (smartStrlen($string) > $length) { 

        $length -= smartStrlen($etc); 

        if (!$break_words && !$middle) { 

            $string = preg_replace(''/\s+?(\S+)?$/'', '''', smartSubstr($string, 0, $length+1)); 

        } 

        if(!$middle) { 

            return smartSubstr($string, 0, $length).$etc; 

        } else { 

            return smartSubstr($string, 0, $length/2) . $etc . smartSubstr($string, -$length/2); 

        } 

    } else { 

        return $string; 

    } 

} 

?>

以上代码完整实现了truncate的原有功能,而且可以同时兼容GB2312和UTF-8编码,在判断字符长度的时候,一个中文字符算1.0,一个英文字符算0.5,所以在截取子字符串的时候不会出现参差不齐的情况.
插件的使用方式没有特别之处,这里简单测试一下:
{$content|smartTruncate:5:".."}($content等于"A中B华C人D民E共F和G国H")

显示:A中B华C.. (中文符号长度算1.0,英文符号长度算0.5,并且考虑省略符号的长度)
不管你是使用GB2312编码还是UTF-8编码,你会发现结果都正确,这也是为什么我在插件名字里加上smart字样的原因之一。

希望本文所述对大家的PHP程序设计有所帮助。

PHP 相关文章推荐
php 向访客和爬虫显示不同的内容
Nov 09 PHP
关于PHP二进制流 逐bit的低位在前算法(详解)
Jun 13 PHP
解析zend studio中直接导入svn中的项目的方法步骤
Jun 21 PHP
ThinkPHP查询语句与关联查询用法实例
Nov 01 PHP
PHP验证信用卡卡号是否正确函数
May 27 PHP
分享php代码将360浏览器导出的favdb的sqlite数据库文件转换为html
Dec 09 PHP
smarty高级特性之对象的使用方法
Dec 25 PHP
PHP中SQL查询语句的id=%d解释(推荐)
Dec 10 PHP
yii框架搜索分页modle写法
Dec 19 PHP
PHP最常用的正则表达式
Feb 13 PHP
Laravel 集成微信用户登录和绑定的实现
Dec 27 PHP
PHP7 标准库修改
Mar 09 PHP
smarty中js的调用方法示例
Oct 27 #PHP
Smarty中常用变量操作符汇总
Oct 27 #PHP
Smarty中调用FCKeditor的方法
Oct 27 #PHP
smarty简单分页的实现方法
Oct 27 #PHP
smarty半小时快速上手入门教程
Oct 27 #PHP
php命令行用法入门实例教程
Oct 27 #PHP
php基于mcrypt的加密解密实例
Oct 27 #PHP
You might like
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
Yii编程开发常见调用技巧集锦
2016/07/15 PHP
PHP连接及操作PostgreSQL数据库的方法详解
2019/01/30 PHP
浅谈PHP无限极分类原理
2019/03/14 PHP
JavaScript中使用正则匹配多条,且获取每条中的分组数据
2010/11/30 Javascript
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
javaScript中的this示例学习详解及工作原理
2014/01/13 Javascript
javascript实现的图片切割多块效果实例
2015/05/07 Javascript
javascript html5实现表单验证
2016/03/01 Javascript
js学习总结之dom2级事件基础知识详解
2017/07/27 Javascript
javascript少儿编程关于返回值的函数内容
2018/05/27 Javascript
countUp.js实现数字动态变化效果
2019/10/17 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
[00:14]PWL:老朋友Mushi拍VLOG与中国玩家问好
2020/11/04 DOTA
[01:16:13]DOTA2-DPC中国联赛 正赛 SAG vs Dragon BO3 第一场 2月22日
2021/03/11 DOTA
使用python编写脚本获取手机当前应用apk的信息
2014/07/21 Python
python进阶教程之循环相关函数range、enumerate、zip
2014/08/30 Python
python统计一个文本中重复行数的方法
2014/11/19 Python
Python字符串和文件操作常用函数分析
2015/04/08 Python
python实现在字符串中查找子字符串的方法
2015/07/11 Python
基python实现多线程网页爬虫
2015/09/06 Python
django 发送手机验证码的示例代码
2018/04/25 Python
Python中的枚举类型示例介绍
2019/01/09 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
如何利用python检测图片是否包含二维码
2020/10/15 Python
华为旗下电子商务平台:华为商城
2016/08/06 全球购物
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
环境工程专业自荐信范文
2014/03/18 职场文书
内科护士节演讲稿
2014/09/11 职场文书
2014光棍节大学生联谊活动方案
2014/10/10 职场文书
教师学期个人总结
2015/02/11 职场文书
2015年机械设备管理工作总结
2015/05/04 职场文书
医学生自荐信范文(2016精选篇)
2016/01/28 职场文书
2019学子的答谢词范本!
2019/07/05 职场文书
2019 入党申请书范文
2019/07/10 职场文书
七年级作文之冬景
2019/11/07 职场文书