PHP 仿网易云的评论盖楼
一、简要
第一次做这种设计,当然有许多不足,希望多多指出。
评论盖楼,就是每条评论一个楼层,而楼层里面可以嵌套很多引用的评论,直接上图
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 仿网易云的评论盖楼的更多相关文章
- 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目
CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...
- [干货教程]仿网易云课堂微信小程序开发实战经验
本篇文章想跟大家分享下:我们公司“湖北诚万兴科技”最近刚帮客户定制开发.目前已上线的“哎咆课堂”微信小程序的开发经验分享.首先大概介绍下这个小程序所涉及到的主要技术点:微信登录.微信支付.微信小程序F ...
- C# WPF 低仿网易云音乐(PC)Banner动画控件
原文:C# WPF 低仿网易云音乐(PC)Banner动画控件 由于技术有限没能做到一模一样的动画,只是粗略地做了一下.动画有点生硬,还有就是没做出网易云音乐的立体感.代码非常简单粗暴,而且我也写有很 ...
- C# WPF 低仿网易云音乐(PC)歌词控件
原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...
- 爬取网易云音乐评论!python 爬虫入门实战(六)selenium 入门!
说到爬虫,第一时间可能就会想到网易云音乐的评论.网易云音乐评论里藏了许多宝藏,那么让我们一起学习如何用 python 挖宝藏吧! 既然是宝藏,肯定是用要用钥匙加密的.打开 Chrome 分析 Head ...
- Flutter仿网易云音乐:播放界面
写在前头 本来是要做一个仿网易云音乐的flutter项目,但是因为最近事情比较多,项目周期跨度会比较长,因此分几个步骤来完成.这是仿网易云音乐项目系列文章的第一篇.没有完全照搬网易云音乐的UI,借鉴了 ...
- 新鲜出炉高仿网易云音乐 APP
我的引语 晚上好,我是吴小龙同学,我的公众号「一分钟GitHub」会推荐 GitHub 上好玩的项目,一分钟 get 一个优秀的开源项目,挖掘开源的价值,欢迎关注我. 项目中成长是最快的,如何成长,就 ...
- python爬虫+词云图,爬取网易云音乐评论
又到了清明时节,用python爬取了网易云音乐<清明雨上>的评论,统计词频和绘制词云图,记录过程中遇到一些问题 爬取网易云音乐的评论 一开始是按照常规思路,分析网页ajax的传参情况.看到 ...
- NetCloud——一个网易云音乐评论抓取和分析的Python库
在17的四月份,我曾经写了一篇关于网易云音乐爬虫的文章,还写了一篇关于评论数据可视化的文章.在这大半年的时间里,有时会有一些朋友给我发私信询问一些关于代码方面的问题.所以我最近抽空干脆将原来的代码整理 ...
随机推荐
- JDK(Linux)
百度云:链接:http://pan.baidu.com/s/1gfa9sEB 密码:bpqr 官网下载网址:http://www.oracle.com/technetwork/java/java ...
- Java EE.JavaBean
JavaBean是一组可移植.可重用.并可以组装到应用程序中的Java类.一个Model类(属性+构造函数).
- Oracle 统计信息介绍
统计信息自动执行需要以下条件满足: dba_autotask_task 字段status值ENABLED dba_autotask_client 字段status值ENABLED dba_auto ...
- 机器学习之使用sklearn构造决策树模型
一.任务基础 导入所需要的库 import matplotlib.pyplot as plt import pandas as pd %matplotlib inline 加载sklearn内置数据集 ...
- js里的window对象
alert(<msg>) 向用户显示对话框窗口并等候其被关闭 blur() 让窗口失去键盘焦 ...
- Linux常用的命令及使用方法
1.请用命令查出ifconfig命令程序的绝对路径 [root@localhost ~]# which ifconfig(ifconfig是linux中用于显示或配置网络设备(网络接口卡)的命令) / ...
- 洛谷P1510 题解
前言: 其实这道题挺水的,但我居然把ta想成了 贪心 啪啪打脸 好了,废话不多说. 思路: step 1:先翻译以下题意,其实就是求出最多消耗多少体力能把东海填满,如果不能填满,就输出"Im ...
- HTML/CSS:图片居中(水平居中和垂直居中)
css图片居中(水平居中和垂直居中) css图片居中分css图片水平居中和垂直居中两种情况,有时候还需要图片同时水平垂直居中, 下面分几种居中情况分别介绍: css图片水平居中 1.利用margin: ...
- requestAnimationFrame 兼容方案
[toc] 编写涉及:css, html, js 在线演示codepen html代码 <div class="roll-box"> <div class=&qu ...
- 利用hash或history实现单页面路由
目录 html代码 css代码 JavaScript代码 hash方式 history 方式 浏览器端代码 服务器端 在chrome(版本 70.0.3538.110)测试正常 编写涉及:css, h ...