thinkPHP实现基于ajax的评论回复功能


Posted in PHP onJune 22, 2018

本文实例讲述了thinkPHP实现基于ajax的评论回复功能。分享给大家供大家参考,具体如下:

控制器代码:

<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
  public function index(){
    $num = M('comment')->count(); //获取评论总数
    $this->assign('num',$num);
    $data=array();
    $data=$this->getCommlist();//获取评论列表
    $this->assign("commlist",$data);
    $this->display('index');
  }
  /**
  *添加评论
  */
  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);
  }
  /**
  *递归获取评论列表
  */
  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;
  }
}

JavaScript代码:

$(function(){
  //点击提交评论内容
  $('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);
          }
        }
      });
    }
  });
  //点击"回复"按钮显示或隐藏回复输入框
  $("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);
     }
  });
})

页面样式代码:

.comment-filed{
  width:640px;
  margin:0 auto;
}
.comment-num{
  text-align: right;
  font-size:14px;
}
.div-txt-submit{
  text-align:right;
  margin-top:8px;
}
.comment-submit{
  background-color:#63B8FF;
  margin-top:15px;
  text-decoration:none;
  color:#fff;
  padding:5px;
  font-size:14px;
}
.txt-commit{
  border:1px solid blue;
  width:620px;
  height: 60px;
  padding: 10px;
}
.txt-reply{
  width: 100%;
  height: 60px;
}
.comment-filed-list{
  margin-top:20px;
}
.comment-list{
  margin-top:2px;
  width:herit;
  height:50px;
  border-top:1px solid gray;
}
.comment-ul{
  list-style:none;
  padding-left:0;
}
.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;
}
.children{
  list-style:none;
  background-color:#FAFAFA;
  padding-left:0;
  margin-left:40px;
}
.children-cm{
  position:relative;
  left:40px;
  top:-40px;
  width:90%;
}

页面布局代码:

<!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" ><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" >回复</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" >回复</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" >回复</a> -->
                      </div>
                    </div>
                  </div>
                </li>
                </volist>
              </ul>
              <!--三级评论end-->
            </li>
            </volist>
          </ul>
          <!--二级评论end-->
        </li>
        </volist>
      </ul>
      <!--一级评论列表end-->
    </div>
  </div>
 <!--评论列表显示区end-->
</div>
</body>
</html>

sql语句:

DROP TABLE IF EXISTS `t_comment`;
CREATE TABLE `t_comment` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
 `parent_id` int(11) NOT NULL COMMENT '上级评论id,若是一级评论则为0',
 `nickname` varchar(100) DEFAULT NULL COMMENT '评论人昵称',
 `head_pic` varchar(400) DEFAULT NULL COMMENT '评论人头像',
 `content` text COMMENT '评论内容',
 `create_time` datetime DEFAULT NULL COMMENT '评论或回复发表时间',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=148 DEFAULT CHARSET=utf8;

页面布局少一个jquery.js请自行加上。

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。

PHP 相关文章推荐
php whois查询API制作方法
Jun 23 PHP
php环境配置之CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI比较?
Oct 17 PHP
php中大括号作用介绍
Mar 22 PHP
PHP获取MSN好友列表类的实现代码
Jun 23 PHP
解析php中获取系统信息的方法
Jun 25 PHP
写一段简单的PHP建立文件夹代码
Jan 06 PHP
php压缩和解压缩字符串的方法
Mar 14 PHP
轻松掌握php设计模式之访问者模式
Sep 23 PHP
php合并数组并保留键值的实现方法
Mar 12 PHP
workerman结合laravel开发在线聊天应用的示例代码
Oct 30 PHP
Laravel学习笔记之Artisan命令生成自定义模板的方法
Nov 22 PHP
PHP中$GLOBALS与global的区别详解
Mar 21 PHP
php strftime函数的详细用法
Jun 21 #PHP
PHP获取本周所有日期或者最近七天所有日期的方法
Jun 20 #PHP
ThinkPHP5.0 图片上传生成缩略图实例代码说明
Jun 20 #PHP
thinkPHP框架实现的短信接口验证码功能示例
Jun 20 #PHP
thinkPHP3.2.2框架行为扩展及demo示例
Jun 19 #PHP
Laravel框架实现的记录SQL日志功能示例
Jun 19 #PHP
PHP 中 var_export、print_r、var_dump 调试中的区别
Jun 19 #PHP
You might like
防止本地用户用fsockopen DDOS攻击对策
2011/11/02 PHP
通过5个php实例细致说明传值与传引用的区别
2012/08/08 PHP
phpinfo() 中 Local Value(局部变量)Master Value(主变量) 的区别
2016/02/03 PHP
joomla实现注册用户添加新字段的方法
2016/05/05 PHP
PHP实现QQ登录的开原理和实现过程
2018/02/04 PHP
PhpStorm本地断点调试的方法步骤
2018/05/21 PHP
PHP面向对象程序设计重载(overloading)操作详解
2019/06/13 PHP
IE6 fixed的完美解决方案
2011/03/31 Javascript
仅IE6/7/8中innerHTML返回值忽略英文空格的问题
2011/04/07 Javascript
文件编码导致jquery失效的解决方法
2013/06/26 Javascript
使用jquery hover事件实现表格的隔行换色功能示例
2013/09/03 Javascript
js完美的div拖拽实例代码
2014/01/22 Javascript
使用upstart把nodejs应用封装为系统服务实例
2014/06/01 NodeJs
JS实现判断滚动条滚到页面底部并执行事件的方法
2014/12/18 Javascript
jquery实现鼠标点击后展开列表内容的导航栏效果
2015/09/14 Javascript
JSON字符串转换JSONObject和JSONArray的方法
2016/06/03 Javascript
基于d3.js实现实时刷新的折线图
2016/08/03 Javascript
angularJs关于指令的一些冷门属性详解
2016/10/24 Javascript
vue.js框架实现表单排序和分页效果
2017/08/09 Javascript
又拍云 Node.js 实现文件上传、删除功能
2018/10/28 Javascript
浅谈webpack+react多页面开发终极架构
2018/11/11 Javascript
仿vue-cli搭建属于自己的脚手架的方法步骤
2019/04/17 Javascript
vue2.x数组劫持原理的实现
2020/04/19 Javascript
js实现三角形粒子运动
2020/09/22 Javascript
Python最基本的输入输出详解
2015/04/25 Python
Python语言实现获取主机名根据端口杀死进程
2016/03/31 Python
django admin后台添加导出excel功能示例代码
2019/05/15 Python
解决Python3.8运行tornado项目报NotImplementedError错误
2020/09/02 Python
python如何构建mock接口服务
2021/01/28 Python
美国珠宝精品店:Opulent Jewelers
2019/08/20 全球购物
董事长秘书职责
2014/01/31 职场文书
副厂长岗位职责
2014/02/02 职场文书
数学与统计学院学生个人职业生涯规划书
2014/02/10 职场文书
党的群众路线教育实践活动领导班子整改措施
2014/10/28 职场文书
芙蓉镇观后感
2015/06/10 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python