// 再还原最初的 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
;