php smarty截取中文字符乱码问题?gb2312/utf-8


Posted in PHP onNovember 07, 2011

一般网站页面的显示都不可避免的会涉及子字符串的截取,这个时候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 相关文章推荐
优化NFR之一 --MSSQL Hello Buffer Overflow
Oct 09 PHP
PHP n个不重复的随机数生成代码
Jun 23 PHP
PHP验证码类代码( 最新修改,完全定制化! )
Dec 02 PHP
Fine Uploader文件上传组件应用介绍
Jan 06 PHP
从零开始学YII2框架(一)通过Composer安装Yii2框架
Aug 20 PHP
彻底删除thinkphp3.1案例blog标签的方法
Dec 05 PHP
PHP5.3以上版本安装ZendOptimizer扩展
Mar 27 PHP
如何通过Linux命令行使用和运行PHP脚本
Jul 29 PHP
php实现的农历算法实例
Aug 11 PHP
php计算年龄精准到年月日
Nov 17 PHP
php实现跨域提交form表单的方法【2种方法】
Oct 17 PHP
php格式文件打开的四种方法
Feb 24 PHP
PHP面向对象概念
Nov 06 #PHP
php 记录进行累加并显示总时长为秒的结果
Nov 04 #PHP
php 按指定元素值去除数组元素的实现方法
Nov 04 #PHP
php数组函数序列之array_search()- 按元素值返回键名
Nov 04 #PHP
php 伪造本地文件包含漏洞的代码
Nov 03 #PHP
有关php运算符的知识大全
Nov 03 #PHP
PHP读取txt文件的内容并赋值给数组的代码
Nov 03 #PHP
You might like
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
Smarty保留变量用法分析
2016/05/23 PHP
PHP安装memcache扩展的步骤讲解
2019/02/14 PHP
Js 中debug方式
2010/02/07 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
JS模板实现方法
2013/04/03 Javascript
如何使用jQuery Draggable和Droppable实现拖拽功能
2013/07/05 Javascript
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
JavaScript结合AJAX_stream实现流式显示
2015/01/08 Javascript
javascript的几种继承方法介绍
2016/03/22 Javascript
深入理解jQuery layui分页控件的使用
2016/08/17 Javascript
JS之if语句对接事件动作逻辑(详解)
2017/06/28 Javascript
深入浅出webpack教程系列_安装与基本打包用法和命令参数详解
2017/09/10 Javascript
提升node.js中使用redis的性能遇到的问题及解决方法
2018/10/30 Javascript
微信小程序实现星级评价效果
2018/12/28 Javascript
vue实现文字加密功能
2019/09/27 Javascript
vue 获取到数据但却渲染不到页面上的解决方法
2020/11/19 Vue.js
[32:39]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第一场 11.04
2020/11/04 DOTA
Python中返回字典键的值的values()方法使用
2015/05/22 Python
浅析Python3爬虫登录模拟
2018/02/07 Python
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
python smtplib模块自动收发邮件功能(一)
2018/05/22 Python
Python3.5内置模块之random模块用法实例分析
2019/04/26 Python
python使用pandas处理excel文件转为csv文件的方法示例
2019/07/18 Python
Python中变量的输入输出实例代码详解
2019/07/28 Python
如何利用python读取micaps文件详解
2020/10/18 Python
花园仓库建筑:Garden Buildings Direct
2018/02/16 全球购物
介绍一下木马病毒的种类
2015/07/26 面试题
旅游管理本科生求职信
2013/10/14 职场文书
毕业生求职信的经典写法
2014/01/31 职场文书
县长群众路线对照检查材料思想汇报
2014/10/02 职场文书
局机关干部群众路线个人对照检查材料思想汇报
2014/10/05 职场文书
致百米运动员广播稿5篇
2014/10/13 职场文书
2015年学生会纪检部工作总结
2015/03/31 职场文书
婚礼上证婚人致辞
2015/07/28 职场文书