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 相关文章推荐
支持oicq头像的留言簿(一)
Oct 09 PHP
PHP程序61条面向对象分析设计的经验小结
Nov 12 PHP
如何给phpcms v9增加类似于phpcms 2008中的关键词表
Jul 01 PHP
php发送post请求函数分享
Mar 06 PHP
smarty简单入门实例
Nov 28 PHP
PHP实现的带超时功能get_headers函数
Feb 10 PHP
PHP输出缓冲控制Output Control系列函数详解
Jul 02 PHP
php如何获取文件的扩展名
Oct 28 PHP
PHP实现图片不变型裁剪及图片按比例裁剪的方法
Jan 14 PHP
php 反斜杠处理函数addslashes()和stripslashes()实例详解
Dec 25 PHP
laravel 中某一字段自增、自减的例子
Oct 11 PHP
php post换行的方法
Feb 03 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将整个网站生成HTML纯静态网页的方法总结
2012/02/05 PHP
php文件上传类完整实例
2016/05/14 PHP
PHP+Mysql无刷新问答评论系统(源码)
2016/12/20 PHP
聊聊 PHP 8 新特性 Attributes
2020/08/19 PHP
JS日历 推荐
2006/12/03 Javascript
从阿里妈妈发现的几个不错的表单验证函数
2007/09/21 Javascript
JavaScript调用堆栈及setTimeout使用方法深入剖析
2013/02/16 Javascript
Javascript设置对象的ReadOnly属性(示例代码)
2013/12/25 Javascript
浅谈轻量级js模板引擎simplite
2015/02/13 Javascript
简述AngularJS的控制器的使用
2015/06/16 Javascript
JavaScript编程的单例设计模讲解
2015/11/10 Javascript
基于JS实现导航条flash导航条
2016/06/17 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(1)
2017/02/20 Javascript
详解webpack打包vue时提取css
2017/05/26 Javascript
jQuery实现节点的追加、替换、删除、复制功能示例
2017/07/11 jQuery
js实现图片跟随鼠标移动效果
2019/10/16 Javascript
微信小程序激励式视频广告组件使用详解
2019/12/06 Javascript
Vue 请求传公共参数的操作
2020/07/31 Javascript
在Vue中使用mockjs代码实例
2020/11/25 Vue.js
[38:39]完美世界DOTA2联赛循环赛 IO vs GXR BO2第二场 11.04
2020/11/05 DOTA
python中使用enumerate函数遍历元素实例
2014/06/16 Python
对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解
2018/06/28 Python
如何安装2019Pycharm最新版本(详细教程)
2019/09/26 Python
python opencv进行图像拼接
2020/03/27 Python
彻底弄明白CSS3的Media Queries(跨平台设计)
2010/07/27 HTML / CSS
美国购物网站:Clickhere2shop
2021/01/28 全球购物
一道输出判断型Java面试题
2014/10/01 面试题
JAVA招聘远程笔试题
2015/07/23 面试题
会计电算化应届生求职信
2013/11/03 职场文书
实习求职信
2013/12/01 职场文书
计生专干事迹
2014/05/28 职场文书
以幸福为主题的活动方案
2014/08/22 职场文书
工作失职检讨书
2015/01/26 职场文书
体育委员竞选稿
2015/11/21 职场文书
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js