Home  >  Article  >  php教程  >  php smarty截取中文字符乱码问题?gb2312/utf-8

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

WBOY
WBOYOriginal
2016-06-13 12:04:52869browse

一般网站页面的显示都不可避免的会涉及子字符串的截取,这个时候truncate就派上用场了,但是它只适合英文用户,对与中文用户来说,使用 truncate会出现乱码,而且对于中文英文混合串来说,截取同样个数的字符串,实际显示长度上却不同,视觉上会显得参差不齐,影像美观。这是因为一个中文的长度大致相当与两个英文的长度。此外,truncate也不能同时兼容GB2312, UTF-8等编码。
改良的smartTruncate: 文件名:modifier.smartTruncate.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 {
$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 {
$start = max(smartStrlen($string) + $start, 0);
}
for($i = 0; $i {
if($start {
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 {
if($length {
break;
}
if(($bytes = ord(substr($string, $j, 1)) > 127 ? $number : 1) > 1)
{
if($length {
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字样的原因之一。
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn