关于PHP截字的那些事儿
这是一个初级问题,新手会关注,同样是一个高级问题,老手也常栽跟头。
我负责公司在线产品的底层开发,对这种基础函数也采用拿来主义。
本以为Discuz的cutstr函数应该很完美,但也难逃公司测试人员的法眼。仔细一看,原来也有BUG。
首先,我们分析一下该函数需要实现的功能。对于我们的用户(这里指开发人员),他们需要得到的结果的让一列文字整齐的截断。
他们并不关注文字的个数,也不关注是何编码,只关注字符位置长度。在PHP中汉字和编码有关,gbk是双字节,utf8三字节。
如果不区分编码,substr直接截取的文字一定会乱码, 这也是整个页面常乱掉的原因之一。
对于文字后面的省略号,也会被占用展现的长度,应该被单独计算。
以下是修改后的函数,欢迎大家拍砖!
define('CHARSET', 'utf-8');
/**
* 截字
*
* @param string $string 被截取的文字
* @param int $plength 字符位置长度(一个汉字占用两个标准字符位置)
* @param string $dot 后缀符号
* @return string
*/
function cutstr($string, $plength=36, $dot = '..') {
$plength = (int)$plength;
$strcut = '';
$strlen = strlen($string);
if(CHARSET=='utf-8'){
$n = $tn = $tnl = $noc = 0;
while($n < $strlen) {
$t = ord($string[$n]);
$tnl = $tn;
if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
$tn = 1; $n++; $noc++;
} elseif(194 <= $t && $t <= 223) {
$tn = 2; $n += 2; $noc += 2;
} elseif(224 <= $t && $t < 239) {
$tn = 3; $n += 3; $noc += 2;
} elseif(240 <= $t && $t <= 247) {
$tn = 4; $n += 4; $noc += 2;
} elseif(248 <= $t && $t <= 251) {
$tn = 5; $n += 5; $noc += 2;
} elseif($t == 252 || $t == 253) {
$tn = 6; $n += 6; $noc += 2;
} else {
$n++;
}
if($noc >= $plength) {
break;
}
}
if($noc > $plength) {
$n -= $tn;
$tn = $tnl;
}
if($strlen>$n){
return substr($string, 0, $n-$tn).$dot;
}else{
return substr($string, 0, $n);
}
}else{
if($strlen <= $plength+strlen($dot)) {
return $string;
}
for($i = 0; $i < $plength; $i++) {
$strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
}
return $strcut.$dot;
}
}
最新评论:
no.116147 new 74.126.186.239 2020-03-24 23:55
no.10232 dd9gdf18g 188.143.232.32 2016-06-08 13:54
no.4241 1 218.29.65.30 2014-06-21 14:13
no.1829 fengge 113.205.45.26 2011-02-26 06:41
no.1822 yuql 113.250.17.225 2011-01-25 13:57
mb_substr相对substr多了一个编码识别,但是一般的服务器都没打开php_mbstring.dll