php无限级分类实现评论及回复功能


Posted in PHP onFebruary 18, 2019

经常在各大论坛或新闻板块详情页面下边看到评论功能,当然不单单是直接发表评论内容那么简单,可以对别人的评论进行回复,别人又可以对你的回复再次评论或回复,如此反复,理论上可以说是没有休止,从技术角度分析很容易想到运用无限级分类技术存储数据,运用递归获取评论层级结构数据,运用ajax实现评论页面交互,这里用thinkphp框架做个简单的demo练练手,为了简化流程这里第三级评论开始停止回复,当然只要在这个基础上稍作修改就可以实现无限回复功能,主要是view层样式修改较麻烦,需花些时间。

一、效果需求分析:

1.在头部可以直接发布一级评论,最新发表的评论显示在最上面,如下效果图

php无限级分类实现评论及回复功能

2.对发表的评论可以回复,回复显示在上级评论下边,形成层级关系,如下效果图

php无限级分类实现评论及回复功能

3.页面操作细节:点击某个评论的回复按钮时,显示回复文本输入框,同时其他评论的回复文本输入框消失,当再次点击该回复按钮时,该文本框消失

4.在最后一级评论(这里设置是第三级)关闭回复功能

5.即时显示评论总数

二、实现思路及细节

1.数据表设计

php无限级分类实现评论及回复功能

2.controller层关键函数:

(1). 递归获取评论列表

/**
*递归获取评论列表
 */
 protected function getCommlist($parent_id = 0,&$result = array()){ 
 $arr = M('comment')->where("parent_id = '".$parent_id."'")->order("create_time desc")->select(); 
 if(empty($arr)){
 return array();
 }
 foreach ($arr as $cm) { 
 $thisArr=&$result[];
 $cm["children"] = $this->getCommlist($cm["id"],$thisArr); 
 $thisArr = $cm;     
 }
 return $result;
 }

(2). 展示评论页面的action

public function index(){ 
 $num = M('comment')->count(); //获取评论总数
 $this->assign('num',$num);
 $data=array();
 $data=$this->getCommlist();//获取评论列表
 $this->assign("commlist",$data);
 $this->display('index');
 }

(3).评论页面ajax访问添加评论的action

/**
*添加评论
 */
 public function addComment(){  
 $data=array();
 if((isset($_POST["comment"]))&&(!empty($_POST["comment"]))){
 $cm = json_decode($_POST["comment"],true);//通过第二个参数true,将json字符串转化为键值对数组
 $cm['create_time']=date('Y-m-d H:i:s',time());
 $newcm = M('comment');
 $id = $newcm->add($cm);

 $cm["id"] = $id;
 $data = $cm;

 $num = M('comment')->count();//统计评论总数
 $data['num']= $num;

 }else{
 $data["error"] = "0";
 }


 echo json_encode($data);
 }

3.view层实现

(1). 展示页面的整体结构设计

php无限级分类实现评论及回复功能

实际效果:

php无限级分类实现评论及回复功能

页面html代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
 <title>php无限级分类实战————评论及回复功能</title>
 <link rel="stylesheet" type="text/css" href="/Public/css/comment.css" rel="external nofollow" >
 <script type="text/javascript" src="/Public/js/jquery-1.11.3.min.js" ></script>
 <script type="text/javascript" src="/Public/js/comment.js" ></script>
</head>
<body>

<div class="comment-filed">
 <!--发表评论区begin-->
 <div>
 <div class="comment-num">
 <span>{$num}条评论</span>
 </div>
 <div>
 <div>
 <textarea class="txt-commit" replyid="0"></textarea>
 </div>
 <div class="div-txt-submit">
  <a class="comment-submit" parent_id="0" style="" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><span style=''>发表评论</span></a>
 </div> 
 </div>
 </div>
 <!--发表评论区end-->

 <!--评论列表显示区begin-->
 <!-- {$commentlist} -->
 <div class="comment-filed-list" >
 <div><span>全部评论</span></div>
 <div class="comment-list" >
  <!--一级评论列表begin-->
  <ul class="comment-ul"> 
  <volist name="commlist" id="data">   
   <li comment_id="{$data.id}">   
   <div >
   <div>
    <img class="head-pic" src="{$data.head_pic}" alt=""> 
   </div>
   <div class="cm">
    <div class="cm-header">
    <span>{$data.nickname}</span>
    <span>{$data.create_time}</span>
    </div>
    <div class="cm-content">
    <p>
     {$data.content}
    </p>
    </div>
    <div class="cm-footer">
    <a class="comment-reply" comment_id="{$data.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a>   
    </div> 
   </div>        
   </div>

   <!--二级评论begin-->
   <ul class="children">
   <volist name="data.children" id="child" >    
   <li comment_id="{$child.id}">   
    <div >
    <div>
     <img class="head-pic" src="{$child.head_pic}" alt=""> 
    </div>
    <div class="children-cm">
     <div class="cm-header">
     <span>{$child.nickname}</span>
     <span>{$child.create_time}</span>
     </div>
     <div class="cm-content">
     <p>
      {$child.content}
     </p>
     </div>
     <div class="cm-footer">    
     <a class="comment-reply" replyswitch="off" comment_id="{$child.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a>
     </div> 
    </div>        
    </div>

    <!--三级评论begin-->
    <ul class="children">
    <volist name="child.children" id="grandson" > 
    <li comment_id="{$grandson.id}">   
     <div >
     <div>
      <img class="head-pic" src="{$grandson.head_pic}" alt=""> 
     </div>
     <div class="children-cm">
      <div class="cm-header">
      <span>{$grandson.nickname}</span>
      <span>{$grandson.create_time}</span>
      </div>
      <div class="cm-content">
      <p>
       {$grandson.content}
      </p>
      </div>
      <div class="cm-footer">    
      <!-- <a class="comment-reply" comment_id="1" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a> -->
      </div> 
     </div>        
     </div>
    </li>
    </volist>
    </ul> 
    <!--三级评论end-->

   </li>
   </volist>
   </ul> 
   <!--二级评论end-->

  </li>
  </volist>         
  </ul>
  <!--一级评论列表end-->
 </div> 
 </div>
 <!--评论列表显示区end-->
</div> 
</body>
</html>

(2). 单个评论信息div结构代码

<div >
 <div>
 <img class="head-pic" src="{$data.head_pic}" alt=""> 
 </div>
 <div class="cm">
 <div class="cm-header">
  <span>{$data.nickname}</span>
  <span>{$data.create_time}</span>
  </div>
 <div class="cm-content">
   <p>
   {$data.content}
   </p>
 </div>
 <div class="cm-footer">
  <a class="comment-reply" comment_id="{$data.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a>   
 </div> 
 </div>        
</div>

对应的效果图:

php无限级分类实现评论及回复功能

对应的css代码:

.head-pic{
 width:40px;
 height:40px; 
}

.cm{
 position:relative;
 top:0px;
 left:40px;
 top:-40px;
 width:600px;
}

.cm-header{
 padding-left:5px;
}

.cm-content{
 padding-left:5px;
}

.cm-footer{
 padding-bottom:15px;
 text-align:right;
 border-bottom: 1px dotted #CCC;
}

.comment-reply{
 text-decoration:none;
 color:gray;
 font-size: 14px;
}

4. JS代码

(1). 提交评论:提交评论的a标签按钮引用了样式comment-submit,在其点击事件中进行ajax操作

$('body').delegate('.comment-submit','click',function(){ 
 var content = $.trim($(this).parent().prev().children("textarea").val());//根据布局结构获取当前评论内容
 $(this).parent().prev().children("textarea").val("");//获取完内容后清空输入框
 if(""==content){
  alert("评论内容不能为空!"); 
 }else{
  var cmdata = new Object();
  cmdata.parent_id = $(this).attr("parent_id");//上级评论id
  cmdata.content = content;
  cmdata.nickname = "游客";//测试用数据
  cmdata.head_pic = "/Public/images/default.jpg";//测试用数据  
  var replyswitch = $(this).attr("replyswitch");//获取回复开关锁属性
  $.ajax({
  type:"POST",
  url:"/index.php/home/index/addComment",
  data:{
   comment:JSON.stringify(cmdata)  
  },
  dataType:"json",  
  success:function(data){
   if(typeof(data.error)=="undefined"){
   $(".comment-reply").next().remove();//删除已存在的所有回复div 
   //更新评论总数   
   $(".comment-num").children("span").html(data.num+"条评论");
   //显示新增评论
   var newli = "";   
   if(cmdata.parent_id == "0"){
    //发表的是一级评论时,添加到一级ul列表中   
    newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'><a class='comment-reply' comment_id='"+data.id+"' href='javascript:void(0);'>回复</a></div></div></div><ul class='children'></ul></li>";    
    $(".comment-ul").prepend(newli);
   }else{
    //否则添加到对应的孩子ul列表中    
    if('off'==replyswitch){//检验出回复关闭锁存在,即三级评论不再提供回复功能    
    newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='children-cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'></div></div></div><ul class='children'></ul></li>";
    }else{//二级评论的回复按钮要添加回复关闭锁属性   
    newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='children-cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'><a class='comment-reply' comment_id='"+data.id+"' href='javascript:void(0);' replyswitch='off' >回复</a></div></div></div><ul class='children'></ul></li>";
    }    
    $("li[comment_id='"+data.parent_id+"']").children("ul").prepend(newli);
   }

   }else{
   //有错误信息
   alert(data.error);
   }

  }
  });
 }


 });

(2).回复评论:回复评论的a标签按钮引用了样式comment-reply,在其点击事件中进行显示或隐藏评论输入框的操作

//点击"回复"按钮显示或隐藏回复输入框
 $("body").delegate(".comment-reply","click",function(){
 if($(this).next().length>0){//判断出回复div已经存在,去除掉
  $(this).next().remove();
  }else{//添加回复div
  $(".comment-reply").next().remove();//删除已存在的所有回复div 
  //添加当前回复div
  var parent_id = $(this).attr("comment_id");//要回复的评论id

  var divhtml = "";
  if('off'==$(this).attr("replyswitch")){//二级评论回复后三级评论不再提供回复功能,将关闭属性附加到"提交回复"按钮"
  divhtml = "<div class='div-reply-txt' style='width:98%;padding:3px;' replyid='2'><div><textarea class='txt-reply' replyid='2' style='width: 100%; height: 60px;'></textarea></div><div style='margin-top:5px;text-align:right;'><a class='comment-submit' parent_id='"+parent_id+"' style='font-size:14px;text-decoration:none;background-color:#63B8FF;' href='javascript:void(0);' replyswitch='off' >提交回复</a></div></div>";
  }else{
  divhtml = "<div class='div-reply-txt' style='width:98%;padding:3px;' replyid='2'><div><textarea class='txt-reply' replyid='2' style='width: 100%; height: 60px;'></textarea></div><div style='margin-top:5px;text-align:right;'><a class='comment-submit' parent_id='"+parent_id+"' style='font-size:14px;text-decoration:none;background-color:#63B8FF;' href='javascript:void(0);'>提交回复</a></div></div>";
  }  
  $(this).after(divhtml);
  }
 });

三、完整代码免费下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
使用sockets:从新闻组中获取文章(一)
Oct 09 PHP
php的控制语句
Oct 09 PHP
php生成的html meta和link标记在body标签里 顶部有个空行
May 18 PHP
PHP CURL模拟登录新浪微博抓取页面内容 基于EaglePHP框架开发
Jan 16 PHP
php实现memcache缓存示例讲解
Dec 04 PHP
ecshop后台编辑器替换成ueditor编辑器
Mar 03 PHP
使用PHP编写发红包程序
Jul 22 PHP
php生成图片验证码的实例讲解
Aug 03 PHP
基于JQuery+PHP编写砸金蛋中奖程序
Sep 08 PHP
php获取ip及网址的简单方法(必看)
Apr 01 PHP
php实现的生成迷宫与迷宫寻址算法完整实例
Nov 06 PHP
php经典趣味算法实例代码
Jan 21 PHP
PHP-FPM 的管理和配置详解
Feb 17 #PHP
PHP get_html_translation_table()函数用法讲解
Feb 16 #PHP
PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
Feb 16 #PHP
PHP封装的mysqli数据库操作类示例
Feb 16 #PHP
PHP fprintf()函数用法讲解
Feb 16 #PHP
PHP explode()函数用法讲解
Feb 15 #PHP
php二维数组按某个键值排序的实例讲解
Feb 15 #PHP
You might like
ADODB类使用
2006/11/25 PHP
php设计模式之单例模式使用示例
2014/01/20 PHP
smarty中常用方法实例总结
2015/08/07 PHP
PHP简单读取xml文件的方法示例
2017/04/20 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
php使用Swoole实现毫秒级定时任务的方法
2020/09/04 PHP
VBScript版代码高亮
2006/06/26 Javascript
浅谈jQuery事件绑定原理
2015/01/02 Javascript
jquery中show()、hide()和toggle()用法实例
2015/01/15 Javascript
JavaScript 模块化编程(笔记)
2015/04/08 Javascript
Javascript小技能总结(推荐)
2016/06/02 Javascript
JQuery学习总结【二】
2016/12/01 Javascript
js实现短信发送倒计时功能(正则验证)
2017/02/10 Javascript
微信小程序开发之左右分栏效果的实例代码
2019/05/20 Javascript
利用js-cookie实现前端设置缓存数据定时失效
2019/06/18 Javascript
详解vue3中组件的非兼容变更
2021/03/03 Vue.js
[01:10:48]完美世界DOTA2联赛PWL S2 GXR vs PXG 第一场 11.18
2020/11/18 DOTA
Python多进程通信Queue、Pipe、Value、Array实例
2014/11/21 Python
利用Python绘制数据的瀑布图的教程
2015/04/07 Python
Python中的with...as用法介绍
2015/05/28 Python
使用Python的Bottle框架写一个简单的服务接口的示例
2015/08/25 Python
python学生信息管理系统
2018/03/13 Python
python实现输入数字的连续加减方法
2018/06/22 Python
浅析python3中的os.path.dirname(__file__)的使用
2018/08/30 Python
Python爬虫使用浏览器cookies:browsercookie过程解析
2019/10/22 Python
关于Python 常用获取元素 Driver 总结
2019/11/24 Python
Python监控服务器实用工具psutil使用解析
2019/12/19 Python
CSS3实现图片抽屉式效果的示例代码
2019/11/06 HTML / CSS
巴西体育用品商店:Lojão dos Esportes
2018/07/21 全球购物
有针对性的求职自荐信
2013/11/14 职场文书
岗位聘任书范文
2014/03/29 职场文书
团队口号大全
2014/06/06 职场文书
2014年社区国庆节活动方案
2014/09/16 职场文书
优秀教研组申报材料
2014/12/26 职场文书
劳保用品管理制度范本
2015/08/06 职场文书
《只有一个地球》教学反思
2016/02/16 职场文书