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版(2)
Oct 09 PHP
Smarty安装配置方法
Apr 10 PHP
一步一步学习PHP(4) php 函数 补充2
Feb 15 PHP
PHP下打开URL地址的几种方法小结
May 16 PHP
php并发对MYSQL造成压力的解决方法
Feb 21 PHP
PHP采用自定义函数实现遍历目录下所有文件的方法
Aug 19 PHP
Javascript与PHP验证用户输入URL地址是否正确
Oct 09 PHP
php封装的单文件(图片)上传类完整实例
Oct 18 PHP
laravel5.6实现数值转换
Oct 23 PHP
浅析PHP echo 和 print 语句
Jun 30 PHP
WordPress免插件实现面包屑导航的示例代码
Aug 20 PHP
PhpStorm 2020.3:新增开箱即用的PHP 8属性(推荐)
Oct 30 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结合ajax实现手机发红包的案例
2016/10/13 PHP
使用phpQuery获取数组的实例
2017/03/13 PHP
浅谈PHP中如何实现Hook机制
2017/11/14 PHP
javascript垃圾收集机制与内存泄漏详细解析
2013/11/11 Javascript
使用js解决由border属性引起的div宽度问题
2013/11/26 Javascript
js中哈希表的几种用法总结
2014/01/28 Javascript
全面解析Bootstrap图片轮播效果
2015/12/03 Javascript
javascript自动恢复文本框点击清除后的默认文本
2016/01/12 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
Angular的自定义指令以及实例
2016/12/26 Javascript
easyui 中的datagrid跨页勾选问题的实现方法
2017/01/18 Javascript
Vue2.0 UI框架ElementUI使用方法详解
2017/04/14 Javascript
获取layer.open弹出层的返回值方法
2018/08/20 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
jQuery实现文本显示一段时间后隐藏的方法分析
2019/06/20 jQuery
javascript中undefined的本质解析
2019/07/31 Javascript
详解Vue数据驱动原理
2020/11/17 Javascript
Python 字符串定义
2009/09/25 Python
详解K-means算法在Python中的实现
2017/12/05 Python
Python入门学习指南分享
2018/04/11 Python
对numpy的array和python中自带的list之间相互转化详解
2018/04/13 Python
python 删除列表里所有空格项的方法总结
2018/04/18 Python
Python 实现中值滤波、均值滤波的方法
2019/01/09 Python
Python3实现的判断环形链表算法示例
2019/03/07 Python
Django打印出在数据库中执行的语句问题
2019/07/25 Python
纯CSS3实现漂亮的input输入框动画样式库(Text input love)
2018/12/29 HTML / CSS
POP文化和音乐灵感的时尚:Hot Topic
2019/06/19 全球购物
校三好学生主要事迹
2014/01/11 职场文书
计算机专业毕业生自我鉴定
2014/01/16 职场文书
致100米运动员广播稿
2014/02/14 职场文书
奖学金个人总结
2015/03/04 职场文书
2015年仓库工作总结
2015/04/09 职场文书
少年派的奇幻漂流观后感
2015/06/08 职场文书
简爱电影观后感
2015/06/10 职场文书
Redis6.0搭建集群Redis-cluster的方法
2021/05/08 Redis
深入理解go slice结构
2021/09/15 Golang