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 相关文章推荐
JS与PHP向函数传递可变参数的区别实例代码
May 18 PHP
php 带逗号千位符数字的处理方法
Jan 10 PHP
php写的AES加密解密类分享
Jun 20 PHP
PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
Mar 07 PHP
php调用KyotoTycoon简单实例
Apr 02 PHP
php编程中echo用逗号和用点号连接的区别
Mar 26 PHP
PHP基于反射机制实现插件的可插拔设计详解
Nov 10 PHP
Json_decode 解析json字符串为NULL的解决方法(必看)
Feb 17 PHP
PHP构造二叉树算法示例
Jun 21 PHP
如何修改Laravel中url()函数生成URL的根地址
Aug 11 PHP
Laravel5.7框架安装与使用学习笔记图文详解
Apr 02 PHP
thinkphp5框架实现数据库读取的数据转换成json格式示例
Oct 10 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_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
AngularJS初始化过程分析(引导程序)
2014/12/06 Javascript
JavaScript中this详解
2015/09/01 Javascript
深入理解jquery中的each用法
2016/12/14 Javascript
用v-html解决Vue.js渲染中html标签不被解析的问题
2016/12/14 Javascript
javascript中神奇的 Date对象小结
2017/10/12 Javascript
微信小程序显示下拉列表功能【附源码下载】
2017/12/12 Javascript
JavaScript设计模式之工厂模式简单实例教程
2018/07/03 Javascript
详解关于React-Router4.0跳转不置顶解决方案
2019/05/10 Javascript
echarts多条折线图动态分层的实现方法
2019/05/24 Javascript
八种Vue组件间通讯方式合集(推荐)
2020/08/18 Javascript
python中enumerate的用法实例解析
2014/08/18 Python
详解Python中DOM方法的动态性
2015/04/11 Python
浅析Python中的join()方法的使用
2015/05/19 Python
Python统计python文件中代码,注释及空白对应的行数示例【测试可用】
2018/07/25 Python
Jupyter notebook 启动闪退问题的解决
2020/04/13 Python
python中rc1什么意思
2020/06/19 Python
keras 模型参数,模型保存,中间结果输出操作
2020/07/06 Python
Pycharm2020.1安装无法启动问题即设置中文插件的方法
2020/08/07 Python
Pythonic版二分查找实现过程原理解析
2020/08/11 Python
英国领先的家庭时尚品牌:Peacocks
2018/01/11 全球购物
在印度上传处方,在线订购药品:Medlife
2019/03/28 全球购物
大学生自我鉴定
2013/12/16 职场文书
汽车专业人才自我鉴定范文
2013/12/29 职场文书
听课评语大全
2014/04/30 职场文书
考试保密承诺书
2014/08/30 职场文书
关于运动会广播稿300字
2014/10/05 职场文书
单位单身证明样本
2014/10/11 职场文书
党的群众路线教育实践活动个人对照检查材料(企业)
2014/11/05 职场文书
2014年食品安全工作总结
2014/12/04 职场文书
家长评语怎么写
2014/12/30 职场文书
公司年夜饭通知
2015/04/25 职场文书
主持稿开场白
2015/06/01 职场文书
导游词之云南丽江-泸沽湖
2019/09/26 职场文书
上个世纪50年代的可穿戴技术:无线电帽子
2022/02/18 无线电