php对包含html标签的字符串进行截取的函数分享


Posted in PHP onJune 19, 2014

这个方法的作用是:php截取含有html标签的字符串,如果标签未闭合就闭合标签,防止未闭合的标签破坏原网页布局。截取完之后将多余的内容替换为...或者其他任意字符,支持锚点指定替换到指定位置。

/*
* ============================== 截取含有 html标签的字符串 =========================
* @param (string) $str   待截取字符串
* @param (int)  $lenth  截取长度
* @param (string) $repalce 超出的内容用$repalce替换之(该参数可以为带有html标签的字符串)
* @param (string) $anchor 截取锚点,如果截取过程中遇到这个标记锚点就截至该锚点处
* @return (string) $result 返回值
* @demo  $res = cut_html_str($str, 256, '...'); //截取256个长度,其余部分用'...'替换
* -------------------------------------------------------------------------------
* $ Author: Wang Jian.	|	Email: wj@yurendu.com	|	Date: 2014/03/16
* ===============================================================================
*/ 
function cut_html_str($str, $lenth, $replace='', $anchor='<!-- break -->'){ 
	$_lenth = mb_strlen($str, "utf-8");	// 统计字符串长度(中、英文都算一个字符)
	if($_lenth <= $lenth){
		return $str;	// 传入的字符串长度小于截取长度,原样返回
	}
	$strlen_var = strlen($str); 	// 统计字符串长度(UTF8编码下-中文算3个字符,英文算一个字符)
	if(strpos($str, '<') === false){ 
		return mb_substr($str, 0, $lenth);	// 不包含 html 标签 ,直接截取
	} 
	if($e = strpos($str, $anchor)){ 
		return mb_substr($str, 0, $e);	// 包含截断标志,优先
	} 
	$html_tag = 0; 	// html 代码标记 
	$result = ''; 	// 摘要字符串
	$html_array = array('left' => array(), 'right' => array()); //记录截取后字符串内出现的 html 标签,开始=>left,结束=>right
	/*
	* 如字符串为:<h3><p><b>a</b></h3>,假设p未闭合,数组则为:array('left'=>array('h3','p','b'), 'right'=>'b','h3');
	* 仅补全 html 标签,<? <% 等其它语言标记,会产生不可预知结果
	*/ 
	for($i = 0; $i < $strlen_var; ++$i) { 
		if(!$lenth) break;	// 遍历完之后跳出
		$current_var = substr($str, $i, 1); // 当前字符
		if($current_var == '<'){ // html 代码开始 
			$html_tag = 1; 
			$html_array_str = ''; 
		}else if($html_tag == 1){ // 一段 html 代码结束 
			if($current_var == '>'){ 
				$html_array_str = trim($html_array_str); //去除首尾空格,如 <br / > < img src="" / > 等可能出现首尾空格
				if(substr($html_array_str, -1) != '/'){ //判断最后一个字符是否为 /,若是,则标签已闭合,不记录
					// 判断第一个字符是否 /,若是,则放在 right 单元 
					$f = substr($html_array_str, 0, 1); 
					if($f == '/'){ 
						$html_array['right'][] = str_replace('/', '', $html_array_str); // 去掉 '/' 
					}else if($f != '?'){ // 若是?,则为 PHP 代码,跳过
						// 若有半角空格,以空格分割,第一个单元为 html 标签。如:<h2 class="a"> <p class="a"> 
						if(strpos($html_array_str, ' ') !== false){ 
						// 分割成2个单元,可能有多个空格,如:<h2 class="" id=""> 
						$html_array['left'][] = strtolower(current(explode(' ', $html_array_str, 2))); 
						}else{ 
						//若没有空格,整个字符串为 html 标签,如:<b> <p> 等,统一转换为小写
						$html_array['left'][] = strtolower($html_array_str); 
						} 
					} 
				} 
				$html_array_str = ''; // 字符串重置
				$html_tag = 0; 
			}else{ 
				$html_array_str .= $current_var; //将< >之间的字符组成一个字符串,用于提取 html 标签
			} 
		}else{ 
			--$lenth; // 非 html 代码才记数
		} 
		$ord_var_c = ord($str{$i}); 
		switch (true) { 
			case (($ord_var_c & 0xE0) == 0xC0): // 2 字节 
				$result .= substr($str, $i, 2); 
				$i += 1; break; 
			case (($ord_var_c & 0xF0) == 0xE0): // 3 字节
				$result .= substr($str, $i, 3); 
				$i += 2; break; 
			case (($ord_var_c & 0xF8) == 0xF0): // 4 字节
				$result .= substr($str, $i, 4); 
				$i += 3; break; 
			case (($ord_var_c & 0xFC) == 0xF8): // 5 字节 
				$result .= substr($str, $i, 5); 
				$i += 4; break; 
			case (($ord_var_c & 0xFE) == 0xFC): // 6 字节
				$result .= substr($str, $i, 6); 
				$i += 5; break; 
			default: // 1 字节 
				$result .= $current_var; 
		} 
	} 
	if($html_array['left']){ //比对左右 html 标签,不足则补全
		$html_array['left'] = array_reverse($html_array['left']); //翻转left数组,补充的顺序应与 html 出现的顺序相反
		foreach($html_array['left'] as $index => $tag){ 
			$key = array_search($tag, $html_array['right']); // 判断该标签是否出现在 right 中
			if($key !== false){ // 出现,从 right 中删除该单元
				unset($html_array['right'][$key]); 
			}else{ // 没有出现,需要补全 
				$result .= '</'.$tag.'>'; 
			} 
		} 
	} 
	return $result.$replace; 
}
PHP 相关文章推荐
深入理解PHP之require/include顺序 推荐
Jan 02 PHP
让你成为更出色的PHP开发者的10个技巧
Feb 25 PHP
PHP file_get_contents设置超时处理方法
Sep 30 PHP
PHP Curl出现403错误的解决办法
May 29 PHP
ThinkPHP中处理表单中的注意事项
Nov 22 PHP
php去除头尾空格的2种方法
Mar 16 PHP
php专用数组排序类ArraySortUtil用法实例
Apr 03 PHP
简单解决新浪SAE无法上传文件的问题
May 13 PHP
php开发时容易忘记的一些技术细节
Feb 03 PHP
Zend Framework教程之配置文件application.ini解析
Mar 10 PHP
简单实现php上传文件功能
Sep 21 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
Feb 28 PHP
php解决抢购秒杀抽奖等大流量并发入库导致的库存负数的问题
Jun 19 #PHP
PHP base64编码后解码乱码的解决办法
Jun 19 #PHP
PHP安全的URL字符串base64编码和解码
Jun 19 #PHP
PHP中的多行字符串传递给JavaScript的两种方法
Jun 19 #PHP
ThinkPHP模板引擎之导入资源文件方法详解
Jun 18 #PHP
ThinkPHP CURD方法之field方法详解
Jun 18 #PHP
ThinkPHP CURD方法之data方法详解
Jun 18 #PHP
You might like
php 用sock技术发送邮件的函数
2007/07/21 PHP
php面向对象全攻略 (九)访问类型
2009/09/30 PHP
php ajax 静态分页过程形式
2011/09/02 PHP
php中根据变量的类型 选择echo或dump
2012/07/05 PHP
php中设置index.php文件为只读的方法
2013/02/06 PHP
php计算程序运行时间的简单例子分享
2014/05/10 PHP
Yii框架中 find findAll 查找出制定的字段的方法对比
2014/09/10 PHP
Yii中CGridView实现批量删除的方法
2015/12/28 PHP
layui数据表格自定义每页条数limit设置
2019/10/26 PHP
Javascript var变量隐式声明方法
2009/10/19 Javascript
通过jQuery打造支持汉字,拼音,英文快速定位查询的超级select插件
2010/06/18 Javascript
NodeJS的模块写法入门(实例代码)
2012/03/07 NodeJs
javascript小数四舍五入多种方法实现
2012/12/23 Javascript
jquery分页插件jpaginate在IE中不兼容问题
2014/04/22 Javascript
jquery获取选中的文本和值的方法
2014/07/08 Javascript
使用命令对象代替switch语句的写法示例
2015/02/28 Javascript
javascript实现简单的贪吃蛇游戏
2015/03/31 Javascript
解决前端跨域问题方案汇总
2016/11/20 Javascript
手机软键盘弹出时影响布局的解决方法
2016/12/15 Javascript
详解node.js平台下Express的session与cookie模块包的配置
2017/04/26 Javascript
nodejs之get/post请求的几种方式小结
2017/07/26 NodeJs
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
2018/07/10 Javascript
vue组件之间数据传递的方法实例分析
2019/02/12 Javascript
Layui 数据表格批量删除和多条件搜索的实例
2019/09/04 Javascript
vue data对象重新赋值无效(未更改)的解决方式
2020/07/24 Javascript
如何在面试中手写出javascript节流和防抖函数
2020/10/22 Javascript
Python变量作用范围实例分析
2015/07/07 Python
python3.5基于TCP实现文件传输
2020/03/20 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
使用Django xadmin 实现修改时间选择器为不可输入状态
2020/03/30 Python
经典导游欢迎词
2015/01/26 职场文书
出纳岗位职责
2015/01/31 职场文书
华清池导游词
2015/02/02 职场文书
2015年社区综治工作总结
2015/04/21 职场文书
小学中队长竞选稿
2015/11/20 职场文书