background image

// 再还原最初的 htmlspecialchars 

$strcut

 = 

str_replace

array

 (

$pre

 . '&' . 

$end

$pre

 . '"' . 

$end

$pre

 . '<' . 

$end

$pre

 . '>' . 

$end

 ), 

array

 ('&', '"', '<', '>' ), 

$strcut

 ); 

$pos

 = 

strrpos

 ( 

$strcut

chr

 ( 1 ) ); 

if

 (

$pos

 !== false) { 

$strcut

 = 

substr

 ( 

$strcut

, 0, 

$pos

 ); 

return

 

$strcut

 . 

$dot

// 最后把截取加上$dot 输出 


 
discuz 版本的最大缺陷在于使用 

strlen

 获取原始字符串的长度,并用来和传入的要截取长度

参数(字节数)进行比较,由于

UTF-8 的中文字符的字节数是不固定的,所以就会面临这

样的窘境:如果要截取

4 个中文字符应该指定多大的截取长度呢?8 字节还是 12 字节

呢?。。。这是无法预计的,也正是因为这个问题

discuz 的 cutstr 实际是有 bug 的,通过下面

的测试结果能看出:

 

代码如下

:

 

$str1

 = "欲穷千里目"; 

echo

 my_cutstr(

$str1

, 10, "...")."\n"; 

// 输出:欲穷千里目... [这是一个 bug,想想是什么原因

导致?

echo

 my_cutstr(

$str1

, 15, "...")."\n"; 

// 输出:欲穷千里目 

 
导致上述

bug 的原因在与 cutstr 函数在截取字符的时候是将一个中文字按 2 个字符算,那么

5 个中文字就是 10 字符,而原始字符串的长度是 15 字节,所以 cutstr 认为“成功地”从 15 字
符的串上截取了

10 个字符,然后加上了“尾巴”。要解决这个 bug 只要在判断一下返回的子

串是否和原始串相同,如果相同就不加

“尾巴”。 

ecshop 版 
代码如下

:

 

/** 
* [ecshop] 基于 PHP 的 mb_substr,iconv_substr 这两个扩展来截取字符串,中文字符都是按
1 个字符长度计算; 
* 该函数仅适用于 utf-8 编码的中文字符串。 

* @param $str 原始字符串 
* @param $length 截取的字符数 
* @param $append 替换截掉部分的结尾字符串 
* @return 返回截取后的字符串 
*/

 

function

 sub_str(

$str

$length

 = 0, 

$append

 = '...') { 

$str

 = trim(

$str

); 

$strlength

 = 

strlen

(

$str

); 

if

 (

$length

 == 0 || 

$length

 >= 

$strlength

) { 

return

 

$str