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开发负载均衡指南
Jul 17 PHP
PHP验证码类代码( 最新修改,完全定制化! )
Dec 02 PHP
Array of country list in PHP with Zend Framework
Oct 17 PHP
关于PHP内存溢出问题的解决方法
Jun 25 PHP
php中autoload的用法总结
Nov 08 PHP
查找php配置文件php.ini所在路径的二种方法
May 26 PHP
cakephp打印sql语句的方法
Feb 13 PHP
Laravel 5框架学习之模型、控制器、视图基础流程
Apr 08 PHP
Yii使用Captcha验证码的方法
Dec 28 PHP
win平台安装配置Nginx+php+mysql 环境
Jan 12 PHP
PHP实现Session入库/存入redis的方法
May 04 PHP
Mac系统完美安装PHP7详细教程
Jun 06 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
用header 发送cookie的php代码
2007/03/16 PHP
php checkbox 取值详细说明
2010/08/19 PHP
php cookie工作原理与实例详解
2016/07/18 PHP
PHP 二级子目录(后台目录)设置二级域名
2017/03/02 PHP
laravel实现上传图片并在页面显示的例子
2019/10/14 PHP
thinkphp5使html5实现动态跳转的例子
2019/10/16 PHP
js实现div弹出层的方法
2014/11/20 Javascript
深入剖析JavaScript中的函数currying柯里化
2016/04/29 Javascript
基于Bootstrap的后台管理面板 Bootstrap Metro Dashboard
2016/06/17 Javascript
微信小程序 progress组件详解及实例代码
2016/10/25 Javascript
javascript 闭包详解及简单实例应用
2016/12/31 Javascript
关于Sequelize连接查询时inlude中model和association的区别详解
2017/02/27 Javascript
纯JS实现可用于页码更换的飞页特效示例
2018/05/21 Javascript
vue3.0 CLI - 1 - npm 安装与初始化的入门教程
2018/09/14 Javascript
详解jQuery-each()方法
2019/03/13 jQuery
JavaScript之Blob对象类型的具体使用方法
2019/11/29 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
解决Vue 移动端点击出现300毫秒延迟的问题
2020/07/21 Javascript
javascript实现移动端触屏拖拽功能
2020/07/29 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
2020/09/22 Javascript
[34:27]DOTA2上海特级锦标赛B组败者赛 VG VS Spirit第一局
2016/02/26 DOTA
Python数据结构与算法之字典树实现方法示例
2017/12/13 Python
python Selenium实现付费音乐批量下载的实现方法
2019/01/24 Python
jenkins配置python脚本定时任务过程图解
2019/10/29 Python
使用python绘制cdf的多种实现方法
2020/02/25 Python
python实现自动打卡的示例代码
2020/10/10 Python
pycharm实现猜数游戏
2020/12/07 Python
草船借箭教学反思
2014/02/03 职场文书
优秀大学生职业生涯规划书
2014/02/27 职场文书
后备干部培训方案
2014/05/22 职场文书
教育局党的群众路线教育实践活动整改方案
2014/09/20 职场文书
80后婚前协议书范本
2014/10/24 职场文书
市委常委会班子党的群众路线教育实践活动整改方案
2014/10/25 职场文书
自查自纠工作情况报告
2014/10/29 职场文书
乡镇党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
喋血孤城观后感
2015/06/08 职场文书