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 相关文章推荐
php 远程关机操作的代码
Dec 05 PHP
PHP获取文件绝对路径的代码(上一级目录)
May 29 PHP
浅谈apache和nginx的rewrite的区别
Feb 22 PHP
在PHP中设置、使用、删除Cookie的解决方法
May 06 PHP
php class中public,private,protected的区别以及实例分析
Jun 18 PHP
php汉字转拼音的示例
Feb 27 PHP
php文件服务实现虚拟挂载其他目录示例
Apr 17 PHP
php判断页面是否是微信打开的示例(微信打开网页)
Apr 25 PHP
php中创建和调用webservice接口示例
Jul 25 PHP
yii2.0使用Plupload实现带缩放功能的多图上传
Dec 22 PHP
Yii2使用dropdownlist实现地区三级联动功能的方法
Jul 18 PHP
tp5框架使用composer实现日志记录功能示例
Jan 10 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
解析如何修改phpmyadmin中的默认登陆超时时间
2013/06/25 PHP
php使用curl并发减少后端访问时间的方法分析
2016/05/12 PHP
Thinkphp5框架中引入Markdown编辑器操作示例
2020/06/03 PHP
Javascript 网页黑白效果实现代码(兼容IE/FF等)
2010/04/23 Javascript
js 获取坐标 通过JS得到当前焦点(鼠标)的坐标属性
2013/01/04 Javascript
Nodejs进程管理模块forever详解
2014/06/01 NodeJs
javascript面向对象特性代码实例
2014/06/12 Javascript
javascript检查浏览器是否支持flash的实现代码
2014/08/14 Javascript
javascript拖拽应用实例
2016/03/25 Javascript
微信JS-SDK坐标位置如何转换为百度地图坐标
2016/07/04 Javascript
js中用cssText设置css样式的简单方法
2016/09/19 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
基于ES6 Array.of的用法(实例讲解)
2017/09/05 Javascript
微信小程序使用form表单获取输入框数据的实例代码
2018/05/17 Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
2018/10/31 Javascript
微信小程序出现wx.getLocation再次授权问题的解决方法分析
2019/01/16 Javascript
详解js动态获取浏览器或页面等容器的宽高
2019/03/13 Javascript
详解React项目中碰到的IE问题
2019/03/14 Javascript
详解js常用分割取字符串的方法
2019/05/15 Javascript
解决vue scoped html样式无效的问题
2020/10/24 Javascript
解决vue打包 npm run build-test突然不动了的问题
2020/11/13 Javascript
[52:41]OG vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/20 DOTA
基于Python函数和变量名解析
2019/07/19 Python
pytorch中的自定义反向传播,求导实例
2020/01/06 Python
浅谈sklearn中predict与predict_proba区别
2020/06/28 Python
解决pytorch 模型复制的一些问题
2021/03/03 Python
鲜为人知的HTML5语音合成功能
2019/05/17 HTML / CSS
PHP高级工程师面试问题推荐
2013/01/18 面试题
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
《雷雨》教学反思
2014/02/20 职场文书
奉献演讲稿范文
2014/05/21 职场文书
消防志愿者活动方案
2014/08/23 职场文书
社区端午节活动总结
2015/02/11 职场文书
信用卡工作证明范本
2015/06/19 职场文书
医护人员继续教育学习心得体会
2016/01/19 职场文书
JS Object构造函数之Object.freeze
2021/04/28 Javascript