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的header和asp中的redirect比较
Oct 09 PHP
如何在PHP中使用Oracle数据库(5)
Oct 09 PHP
php 301转向实现代码
Sep 18 PHP
PHP 实现多服务器共享 SESSION 数据
Aug 15 PHP
PHP调用C#开发的dll类库方法
Jul 28 PHP
php格式化日期实例分析
Nov 12 PHP
php数组添加元素方法小结
Dec 20 PHP
php比较两个字符串长度的方法
Jul 13 PHP
PHP中each与list用法分析
Jan 08 PHP
详解PHP防止直接访问.php 文件的实现方法
Jul 28 PHP
PHP压缩图片功能的介绍
Mar 21 PHP
Laravel 5.5 异常处理 &amp; 错误日志的解决
Oct 17 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中time()和mktime()方法的区别
2013/09/28 PHP
调整PHP的性能
2013/10/30 PHP
php file_get_contents抓取Gzip网页乱码的三种解决方法
2013/11/12 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
js png图片(有含有透明)在IE6中为什么不透明了
2010/02/07 Javascript
JavaScript 对象链式操作测试代码
2010/04/25 Javascript
jquery.validate使用攻略 第一部
2010/07/01 Javascript
Javascript图像处理—平滑处理实现原理
2012/12/28 Javascript
JS自动适应的图片弹窗实例
2013/06/29 Javascript
jquery mobile实现拨打电话功能的几种方法
2013/08/05 Javascript
js实现无缝滚动特效
2015/12/20 Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
2016/09/04 Javascript
jQuery实现的手风琴侧边菜单效果
2017/03/29 jQuery
Vue ElementUI之Form表单验证遇到的问题
2017/08/21 Javascript
中高级前端必须了解的JS中的内存管理(推荐)
2019/07/04 Javascript
python 利用pandas将arff文件转csv文件的方法
2019/02/12 Python
python实现函数极小值
2019/07/10 Python
tesserocr与pytesseract模块的使用方法解析
2019/08/30 Python
Django模板导入母版继承和自定义返回Html片段过程解析
2019/09/18 Python
利用pandas向一个csv文件追加写入数据的实现示例
2020/04/23 Python
基于python3.7利用Motor来异步读写Mongodb提高效率(推荐)
2020/04/29 Python
python查看矩阵的行列号以及维数方式
2020/05/22 Python
使用python创建Excel工作簿及工作表过程图解
2020/05/27 Python
无谷物狗粮:Pooch & Mutt
2018/05/23 全球购物
程序员经常用到的UNIX命令
2015/04/13 面试题
哈弗商学院毕业生求职信
2014/02/26 职场文书
升旗仪式演讲稿
2014/05/08 职场文书
社区清明节活动总结
2014/07/04 职场文书
一份文言文检讨书
2014/09/13 职场文书
防灾减灾标语
2014/10/07 职场文书
2014年文明创建工作总结
2014/11/25 职场文书
2014学生会工作总结报告
2014/12/02 职场文书
安全生产先进个人事迹材料
2014/12/30 职场文书
党支部考察意见范文
2015/06/02 职场文书
萤火虫之墓观后感
2015/06/05 职场文书
温馨祝福晨语:美丽的一天从我的问候开始
2019/11/28 职场文书