一、简要

  第一次做这种设计,当然有许多不足,希望多多指出。

  评论盖楼,就是每条评论一个楼层,而楼层里面可以嵌套很多引用的评论,直接上图

  

  A:牛什么牛(见图 Top4)

  B回复A:好牛啊。(所以这里就嵌套了A的内容,见图Top3)

  C回复B:多谢。(这里同样嵌套B的内容以及B引用的内容,见图Top2)

二、数据库设计

  2.1、评论表设计的sql语句  

 CREATE TABLE `comment` (
      `id_comment` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论ID',
      `id_at` int(11) NOT NULL DEFAULT '' COMMENT '文章Id',
      `id_wx_from` int(11) NOT NULL DEFAULT '' COMMENT '发布者的ID',
      `content` longtext COMMENT '评论内容',
      `time_create` int(11) NOT NULL DEFAULT '' COMMENT '加入时间',
      `path` varchar(255) DEFAULT NULL COMMENT '回复的ID路径:1/2/3/5',
      `num_praise` int(11) NOT NULL DEFAULT '' COMMENT '点赞次数',
      `status` tinyint(4) NOT NULL DEFAULT '' COMMENT '状态',
      `re_comment_id` int(11) NOT NULL DEFAULT '' COMMENT '引用的回复Id',
      `like_ids` longtext COMMENT '点赞用户Ids',
      PRIMARY KEY (`id_comment`)
    ) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;

  

  2.2、评论表的视图 

    

 CREATE VIEW `view_all_comment` AS
      select `c`.`id_comment` AS `commentid`,`c`.`id_wx_from` AS `fromid`,
`u`.`username` AS `fromname`,`u`.`cover` AS `fromcover`,
`c`.`content` AS `content`,`u2`.`id_wx` AS `originid`,
`u2`.`username` AS `originname`,`u2`.`cover` AS `origincover`,
`c2`.`content` AS `origincontent`,
`c`.`time_create` AS `time`,
`c`.`status` AS `status`,`c`.`path` AS `path`,`c`.`num_praise` AS `num_praise`,`c`.`like_ids` AS `like_ids`,`p`.`id_at` AS `id_at`,`p`.`title` AS `title`
      from ((((`comment` `c`
      left join `wx_user` `u` on((`c`.`id_wx_from` = `u`.`id_wx`)))
      left join `article` `p` on((`c`.`id_at` = `p`.`id_at`)))
      left join `comment` `c2` on((`c`.`re_comment_id` = `c2`.`id_comment`))) left join `wx_user` `u2` on((`c2`.`id_wx_from` = `u2`.`id_wx`)))
      order by `c`.`time_create` ;

 

    视图需要注意的是:分别连接一次评论表和两次用户表,是为了获取评论和被评论的内容、发布者和接受者的用户信息。此处为了方便程序读取信息,数据库设计知识尚浅,不知是否妥当。

    

三、评论读取接口(PHP+Yii2)

  3.1、前端需要的接口格式

 [{
name: '阿萨德',
headPic:require('../../assets/action.jpg'),
like: 7633,
content: '感谢撒发生的分里卡享哈哈阿萨德里卡多巴拉巴享哈哈阿萨德里卡多巴拉巴享哈哈阿萨德里卡多巴拉巴多巴拉巴拉',
time: '2017-06-20',
oldComment: []
}, {
name: '蒂法',
headPic:require('../../assets/action.jpg'),
like: 134,
content: '感谢楼主分享大事发生',
time: '2017-06-20',
oldComment: [{
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}, {
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}, {
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}, {
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}, {
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}, {
name: 'CHOWCHIHANG',
comment: '大夫敢死队风格对方是个豆腐干地方供电所覆盖豆腐干受到广泛的斯蒂芬豆腐干斯蒂芬。'
}]
}]

  3.2、获取全部评论的接口以及数据封装 

  /**
* 【根据文章Id获取更多评论(分页获取)】
* 20170724
*
* @param int $id_at 文章Id
* @param int $pageIndex 页码
* @param int $pageSize 每页条数
* @return array 返回的数组
*
*/
public function getMoreCommentsByAtId($id_at, $uid, $pageIndex, $pageSize)
{
//0、判断数据数据是否有误
if(!is_numeric($id_at) || !is_numeric($pageSize) || !is_numeric($pageIndex) || !is_numeric($uid)){
return $this->reErrorMsg(401);
} //1、读取所有原始数据(分页获取)
$rst = (new Query)
->select('commentid as id, fromname as name, fromcover as headPic, num_praise as like, content, time, path, like_ids')
->from('view_all_comment')
->where(['id_at'=>$id_at])
->andWhere('status IN ('.implode(',', [9,10]).')')
->orderBy('time desc')
->offset($pageSize*($pageIndex -1))
->limit($pageSize)
->asArray()
->all(); //2、处理时间和数据整理
foreach ($rst as &$row){
//[ 20170818 验证是否点赞
$ids = [];
if(!empty($row['like_ids'])) {
$ids = explode(',', $row['like_ids']);
} if(in_array($uid, $ids)){
$row['liked'] = true;
}else{
$row['liked'] = false;
}
unset($row['like_ids']);
// 20170818 ] $row['time'] = date('Y-m-d',$row['time']);
if(empty($row['path'])){
$row['oldComment'] = [];//回复作者
unset($row['path']);//去掉此列
continue;
}
//2.1 回复其他读者,楼层
$ids = explode('/',$row['path']);//path => 1/2/3 //按照IN顺序排序
$sql = "SELECT `commentid` AS `id`, `fromname` AS `name`, `content` AS `comment` FROM `view_all_comment` WHERE (`id_at`={$id_at}) AND (`status` IN (".implode(',', [9,10]).")) AND (commentid IN(".implode(',',$ids).")) ORDER BY field(`commentid`, ".implode(',', $ids).")";
$oldComment = $this->findBySql($sql)->asArray()->all(); $row['oldComment'] = $oldComment;
unset($row['path']);
} return $rst;
}

四、评论写入接口

  4.1 Yii的方式

 /**
* 【发布评论】
* 20170725
* 20170818
*
* @return array
*/
public function actionPostComment(){
$model = new TblComment();
if($model->load(Yii::$app->request->post()) && $model->validate()){ if( isset($model->re_comment_id) && $model->re_comment_id != 0){
$remodel = TblComment::findOne($model->re_comment_id);
if(!$remodel){
return $this->retMsg('401');//保存失败
} if(empty($remodel->path)){
$model->path = $model->re_comment_id;
}else {
$model->path = $remodel->path . '/' . $model->re_comment_id;// 1/2/3
}
} if(!$model->save()){
return $this->retMsg('400');//保存失败
}
return $this->retMsg('200');//操作成
}else{
return $this->retMsg('401');//数据格式错误
} }

    说明:发表评论需求的数据:re_comment_id 引用的评论Id,content:评论内容,文章Id,以及用户Id

      path表示为引用的楼层,判断是否为空

  4.2 TP5的方式

 /**
* 【发布评论】
* 20170725
* 20170818
*
* @return array
*/
public function Post_Comment(){
try{
$data = input();//获取POST实体数据 $model =$this->commentModel;//对应评论表
$path = null; //评论引用的楼层
$remodel = $this->commentModel->where(['id_comment'=> $data['re_comment_id']])->find(); //获取所引用的评论model //处理path,空则直接赋值,否则追加 '/re_comment_id'
if(empty($remodel->path)){
$path = $data['re_comment_id'];
}else {
$path = $remodel->path . '/' . $data['re_comment_id'];// 1/2/3
} //组装数据
$lists[] = [
'id_at' => $data['id_at'], //文章Id
'id_wx_from' => $this->uid, //用户Id,后面直接读取session
'content' => $data['content'], //评论内容
'path'=>$path, //楼层路径
'time_create'=> time(), //加入时间
'status' => 9, //状态 9 => 未读, 10 => 已读
're_comment_id' => $data['re_comment_id'] //引用的评论Id
]; if($model->saveAll($lists)){
return $this->retMsg('200');//操作成
}else{
return $this->retMsg('400');//保存失败
}
}catch(Exection $e){
return $this->retMsg('401');//数据格式错误
} }

最新文章

  1. C#窗体程序【用户控件-窗体】委托事件
  2. xml转义字符
  3. android之视频播放
  4. 小学生玩ACM----广搜
  5. asp.net web api 开发时应当注意的事项
  6. ThinkPHP函数详解系列
  7. Shell上传文件到ftp
  8. 线性回归,logistic回归和一般回归
  9. D - Digging(01背包,贪心)
  10. golang 数组反转
  11. MySQL数据库基础(三)(操作数据表中的记录)
  12. eclipse解决maven编码UTF-8的不可映射字符
  13. python调用远程chromedriver.exe、selenium抓包方法
  14. linux:gpg加密和解密
  15. android include使用[转]
  16. [转载]嵌入式C语言中的Doxygen注释模板
  17. 用正则表达式输出rdf文档的三元组格式数据
  18. [POJ1704]Georgia and Bob 博弈论
  19. 翻译-QPKG开发工具快速开始指南
  20. Nginx 502 Bad Gateway 解决方法

热门文章

  1. springboot的邮件服务
  2. MicroPython TPYBoard v201 简易家庭气象站的实现过程
  3. RocketMQ中Producer消息的发送
  4. 完美解决windows10磁盘占用100%并出现卡顿、假死无反应
  5. JAVA常用的集合类
  6. python自动化测试框架unittest
  7. LeetCode :2.两数相加 解题报告及算法优化思路
  8. (15)ASP.NET Core Web主机(IWebHostBuilder)
  9. 在vue项目中引入阿里图标库小记
  10. 常用maven 命令