关于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.10232 dd9gdf18g 188.143.232.32 2016-06-08 13:54

As Charlie Sheen says, this article is "WN!INIGN"

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() 也可..
fangzi 2011-01-25 20:44

mb_substr相对substr多了一个编码识别,但是一般的服务器都没打开php_mbstring.dll

发表评论:

邮箱: