php截取字符串,完美html自动闭合
//截取字符串, html自动闭合
public function str_cut_html($string, $length=450) {
//截取原指定长度
$substr=mb_substr($string, 0, $length, 'UTF-8');
//echo $string;die();
//剩余部分
$remain=mb_substr($string, $length,mb_strlen($string, 'UTF-8'),'UTF-8');
//echo $remain;die();
//剩余小于150 直接使用原string
if(strlen($remain)<150) return $string;
//解决前面截取出现断开标签的问题,如<div>被截成<d <等
$substr_60=mb_substr($substr, -60, 60, 'UTF-8'); //被截取的字符串后60字符
//echo $substr_60;die();
$remain_60=mb_substr($remain, 0, 60, 'UTF-8'); //剩余前60字符
//echo $remain_60;die();
//剩余前60字符标签数
preg_match_all('/(<.*?>)/is',$remain_60,$_tags11);
//print_r($_tages);die();
$tags11=(isset($_tags11[1]) && $_tags11[1]) ? $_tags11[1] : array();
$tags11=count($tags11);
//print_r($tags11);die();
//被截取的字符串后60字符标签数
preg_match_all('/(<.*?>)/is',$substr_60,$_tags22);
//print_r($_tages);die();
$tags22=(isset($_tags22[1]) && $_tags22[1]) ? $_tags22[1] : array();
$tags22=count($tags22);
//print_r($tags22);die();
//前后120个字符标签数
preg_match_all('/(<.*?>)/is',$substr_60.$remain_60,$_tags33);
//print_r($_tages);die();
$tags33=(isset($_tags33[1]) && $_tags33[1]) ? $_tags33[1] : array();
$tags33=count($tags33);
//print_r($tags33);die();
//存在断开标签
$bbb='';
if(($tags11+$tags22)<$tags33) {
$r=strpos($remain_60, '>'); //第一个标签右>的位置
$bbb=mb_substr($remain_60, 0, $r+1, 'UTF-8');
$remain=mb_substr($remain, $r+1);
}
//echo $r;die();
//echo $bbb;die();
//补全断开标签
$substr=$substr.$bbb;
//echo $substr;die();
//匹配截取内容中所有完整标签
preg_match_all('/(<.*?>)/is',$substr,$_tages);
//print_r($_tages);die();
$tages=(isset($_tages[1]) && $_tages[1]) ? $_tages[1] : array();
//print_r($tages);die();
//自闭合标签集特殊处理
$ignore=array('<br />','<hr />','<br/>','<hr/>', '<img>', '<textarea',
'<input>', '<link>', '<source>',
'<embed>', '<frame>', '<basefont>','<base>','<col>',
);
//开始结束标签集统计
$be=$en=array();
//$_tmp=array();
foreach($tages as $v) {
$v=str_replace(array(' ',' '), array(' ',' ') ,strtolower($v));
//将<img src="" <input="" <div class="" id="" 等变为<img> <input> <div>
if(strpos($v, "'") || strpos($v, '"')) {
$v=substr($v, 0 , strpos($v, ' ')).'>';
}
if(in_array($v, $ignore)) continue;
if(strpos('@@@'.$v, '/')) {
if(isset($en[$v])) {
$en[$v]++;
} else {
$en[$v]=1;
}
} else {
if(isset($be[$v])) {
$be[$v]++;
} else {
$be[$v]=1;
}
}
//$_tmp[]=$v;
}
//print_r($be);print_r($en);die();
//需要被闭合的标签位置统计
$where=array();
foreach($be as $k=>$c) {
$k=str_replace('<','</',$k);
//echo $k;die();
if(isset($en[$k]) && $c==$en[$k]) continue; //标签闭合无问题
if(isset($en[$k]) && $c<$en[$k]) continue; //标签多余,属于编辑问题,不处理
$d=isset($en[$k]) ? $c-$en[$k] : $c; //开始标签比闭合标签多的次数
//echo $k.$d;die();
$need[$k]=$d;
$start=0;
for($i=1; $i<=$d; $i++) {
$aa=strpos($remain, $k, $start>0?($start+strlen($k)):$start); //每个未闭合标签位置
$start=$aa>0?$aa:0;
$where[$k]=$start+strlen($k);
}
}
//print_r($where);die();
sort($where);
//print_r($where);die();
$last=array_pop($where);
//echo $last;die();
//截取后面被闭合标签及前面内容
$need=substr($remain, 0, $last);
//echo $need;die();
$substr.=$need;
return $substr;
}