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 相关文章推荐
桌面中心(三)修改数据库
Oct 09 PHP
PHP的ASP防火墙
Oct 09 PHP
删除及到期域名的查看(抢域名必备哦)
May 14 PHP
简单PHP上传图片、删除图片实现代码
May 12 PHP
php 模拟get_headers函数的代码示例
Apr 27 PHP
Drupal7连接多个数据库及常见问题解决
Mar 02 PHP
php去除html标记的原生函数详解
Jan 27 PHP
PHP实现简单数字分页效果
Jul 26 PHP
Yii视图CGridView列表用法实例分析
Jul 12 PHP
thinkPHP实现多字段模糊匹配查询的方法
Dec 01 PHP
解决Laravel无法使用COOKIE和SESSION的问题
Oct 16 PHP
Yii框架 session 数据库存储操作方法示例
Nov 18 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调用mysql存储过程
2007/02/14 PHP
php连接mysql数据库代码
2009/03/10 PHP
PHP中的按位与和按位或操作示例
2014/01/27 PHP
PHP内核探索:变量概述
2014/01/30 PHP
IE6,IE7,IE8下使用Javascript记录光标选中范围(已补全)
2011/08/28 Javascript
LABjs、RequireJS、SeaJS的区别
2014/03/04 Javascript
JS实现从网页顶部掉下弹出层效果的方法
2015/08/06 Javascript
JavaScript实现将数组数据添加到Select下拉框的方法
2015/08/21 Javascript
javascript中href和replace的比较(详解)
2016/11/25 Javascript
Underscore之Array_动力节点Java学院整理
2017/07/10 Javascript
Express使用html模板的详细代码
2017/09/18 Javascript
JavaScript中关于class的调用方法
2017/11/28 Javascript
vue.js将时间戳转化为日期格式的实现代码
2018/06/05 Javascript
微信小程序 Animation实现图片旋转动画示例
2018/08/22 Javascript
Angular5中状态管理的实现
2018/09/03 Javascript
vue实现点击追加选中样式效果
2019/11/01 Javascript
使用js和canvas实现时钟效果
2020/09/08 Javascript
[01:11:21]DOTA2-DPC中国联赛 正赛 VG vs Elephant BO3 第一场 3月6日
2021/03/11 DOTA
python实现的解析crontab配置文件代码
2014/06/30 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
德国原装品牌香水、化妆品和手表网站:BRASTY.DE
2016/10/16 全球购物
美国专业级皮肤病和spa品质护肤品的高级零售网站:SkinCareRx
2017/02/06 全球购物
StubHub西班牙:购买和出售全球活动门票
2017/06/05 全球购物
东南亚冒险旅行与活动:Adventoro
2019/10/16 全球购物
经典c++面试题四
2015/05/14 面试题
采购部主管岗位职责
2014/01/01 职场文书
校运会广播稿100字
2014/01/27 职场文书
安全生产计划书
2014/05/04 职场文书
质量负责人任命书
2014/06/06 职场文书
银行求职自荐书
2014/06/25 职场文书
教师个人事迹材料
2014/12/17 职场文书
2014年学生党支部工作总结
2014/12/20 职场文书
叶问观后感
2015/06/15 职场文书
房产遗嘱范本
2015/08/06 职场文书
深入理解python多线程编程
2021/04/18 Python