一、简要

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

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

  

  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');//数据格式错误
} }

PHP 仿网易云的评论盖楼的更多相关文章

  1. 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目

    CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...

  2. [干货教程]仿网易云课堂微信小程序开发实战经验

    本篇文章想跟大家分享下:我们公司“湖北诚万兴科技”最近刚帮客户定制开发.目前已上线的“哎咆课堂”微信小程序的开发经验分享.首先大概介绍下这个小程序所涉及到的主要技术点:微信登录.微信支付.微信小程序F ...

  3. C# WPF 低仿网易云音乐(PC)Banner动画控件

    原文:C# WPF 低仿网易云音乐(PC)Banner动画控件 由于技术有限没能做到一模一样的动画,只是粗略地做了一下.动画有点生硬,还有就是没做出网易云音乐的立体感.代码非常简单粗暴,而且我也写有很 ...

  4. C# WPF 低仿网易云音乐(PC)歌词控件

    原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...

  5. 爬取网易云音乐评论!python 爬虫入门实战(六)selenium 入门!

    说到爬虫,第一时间可能就会想到网易云音乐的评论.网易云音乐评论里藏了许多宝藏,那么让我们一起学习如何用 python 挖宝藏吧! 既然是宝藏,肯定是用要用钥匙加密的.打开 Chrome 分析 Head ...

  6. Flutter仿网易云音乐:播放界面

    写在前头 本来是要做一个仿网易云音乐的flutter项目,但是因为最近事情比较多,项目周期跨度会比较长,因此分几个步骤来完成.这是仿网易云音乐项目系列文章的第一篇.没有完全照搬网易云音乐的UI,借鉴了 ...

  7. 新鲜出炉高仿网易云音乐 APP

    我的引语 晚上好,我是吴小龙同学,我的公众号「一分钟GitHub」会推荐 GitHub 上好玩的项目,一分钟 get 一个优秀的开源项目,挖掘开源的价值,欢迎关注我. 项目中成长是最快的,如何成长,就 ...

  8. python爬虫+词云图,爬取网易云音乐评论

    又到了清明时节,用python爬取了网易云音乐<清明雨上>的评论,统计词频和绘制词云图,记录过程中遇到一些问题 爬取网易云音乐的评论 一开始是按照常规思路,分析网页ajax的传参情况.看到 ...

  9. NetCloud——一个网易云音乐评论抓取和分析的Python库

    在17的四月份,我曾经写了一篇关于网易云音乐爬虫的文章,还写了一篇关于评论数据可视化的文章.在这大半年的时间里,有时会有一些朋友给我发私信询问一些关于代码方面的问题.所以我最近抽空干脆将原来的代码整理 ...

随机推荐

  1. python使用kazoo操作zookeeper时候出现的"kazoo.exceptions.ConnectionLoss"错误

    在往zk中写入数据的时候,突然遇到 “kazoo.exceptions.ConnectionLoss“错误,然而对zk链接进行检查,在set之前状态是”CONNECT“. 经过测试后发现是因为写入的字 ...

  2. 华为matebook14vm虚拟机错误

    1.创建时显示不支持64位虚拟机 测试环境: 华为matebook14 window10 专业工作站版  1903   问题描述: 创建虚拟机时显示:此主机不支持64位解决方案   问题参考: 参考1 ...

  3. windows server 2008 R2中建立ftp站点

    在windows server 2008 R2中建立ftp站点,要遵循以下步骤: (1) 开启IIS中的ftp服务: (2) 在IIS中建立ftp站点. 具体过程如下: (1) 开启IIS中的ftp服 ...

  4. gradle脚本源码查看环境搭建

    背景 我刚入门学习gradle时,网上资料都是说通过gradle的api查看并学习脚本编写,但是api一般只有接口说明,并不能深入了解各个api的实现逻辑,有时就会对一些脚本的写法感到疑惑.通过搭建源 ...

  5. S3 介绍

    S3 是ceph rgw的基础,在学习RGW之前,先了解S3.

  6. Eclipse中代码自动添加注释及代码注释模板

    介绍 为了提高代码的可读性以及为了有些代码有洁癖的人的需求,我们要从学生到职业进行迈进的过程中,必须把以前的那种代码可读性不高的习惯改掉,因为我们必须要与企业接轨.. 好了,废话不多说,反正就是提升自 ...

  7. 旁友数独会伐啦?python秒解数独了解下伐啦?

    前几天和隔壁邻居玩斗地主被发现了,牌被没收了,斗地主是斗不了了,但我还想和邻居玩耍.如果你还想斗斗地主,戳:趁老王不在,和隔壁邻居斗斗地主,比比大小 想破脑袋终于让我想到一个游戏,数独!什么叫数独?数 ...

  8. 图像反转(一些基本的灰度变换函数)基本原理及Python实现

    1. 基本原理 获取像素值在[0, L]范围内的图像的反转图像,即为负片.适用于增强图像中白色或者灰色的区域,尤其当黑色在图片中占主地位时候 $$T(r) = L-r$$ 2. 运行结果 图源自ski ...

  9. 用CSS来定义<p>标签,要求实现以下效果:字体颜色再IE6下为黑色,IE7下为红色,IE8下为绿色,其他浏览器下为黄色。

    <!DOCTYPE html><html><head><meta charset="utf-8"><meta name=&qu ...

  10. Unity实现放大缩小以及相机位置平移实现拖拽效果

    放大缩小功能是游戏开发中用到的功能,今天就来讲一下Unity中放大缩小怎么实现. 1.IDragHandler, IBeginDragHandler, IEndDragHandler这三个接口是Uni ...