今天刚交付了一个项目,其中一项功能是自由评论,就是可以针对一篇文章在评论区,针对任意位置进行插入评论,类似于Laravel官网的评论区一样的功能:
文章图片
其中可以针对任何一个人进行回复.说白一点就是多叉树,类似的结构如下:
文章图片
文章的id就是根节点,每一个子节点都保存着上一级节点的id,同级节点之间使用根据创建时间进行先后排序.根据上述信息,我们的数据结构如下:
数据结构
- id 主键
- content 评论的内容
- userInfo 发布该评论的用户信息.这里只拿一个字段起演示作用
- create_time 该评论的创建时间,一定要使用int类型的时间戳,这样才好进行大小比较
- parent_id 父级的id
- level 级数,表示本条信息在多叉树中的第几级,主要是为了美化输出
id | content | create_time | parent_id | level |
---|---|---|---|---|
1 | 根节点 | 1 | 0 | 1 |
2 | 子节点1 | 2 | 1 | 2 |
3 | 子节点2 | 3 | 1 | 2 |
4 | 子节点3 | 4 | 1 | 2 |
5 | 子节点4 | 5 | 4 | 3 |
6 | 子节点5 | 6 | 5 | 4 |
… |
create_time
直接使用1,2,3,4等表示.接下来就是如何处理从数据库中读取出来的值了.
递归读取多叉树 这里使用的语言是PHP,当然,知道什么原理的话,语言都是可以改的.首先,说一下我们最终想要获取的数据结构:
$returnData=https://www.it610.com/article/[
0=>[
'id'=>1,
'content'=>'子节点1'
'userinfo'=>[],
'create_time'=>1,
'parent_id'=>0,
'level'=>1
],
1=>[
'id'=>11,
'content'=>'子节点11'
'userinfo'=>[],
'create_time'=>11,
'parent_id'=>1,
'level'=>3
],
2=>[
'id'=>12,
'content'=>'子节点12'
'userinfo'=>[],
'create_time'=>12,
'parent_id'=>11,
'level'=>3
]
];
就是将以上多叉树的结构转换成2维数组的形式,其中所有
level
为2,或者parent_id
为0的项,表示根节点下的第一层数据,而该数据之后的项,除非也满足上述条件,否则就是该节点下的全部子节点.为了实现上述目标,我们必须遍历该多叉树,主要就是要靠递归实现.该递归的函数的目的只有一个:
找儿子,简称找子(节点)
为了有一个全局变量存储每次遍历后的值,所以将上述方法写在一个类中:
class Family{
// 存储最后的返回结果
protected $relationship;
// 存储要遍历的数据
protected $data;
// 构造函数,传入要遍历的数据,并保存在全部变量中
public function __constructor($data){
$this->data=https://www.it610.com/article/$data;
}
/**
* 递归函数,作用是获取该节点下的第一个子节点信息,并自动寻找下一个
* @param $fatherInfo array
**/
protected function where_are_you_my_son($fatherInfo){
// 获取要遍历的数据
$data=$this->$data;
foreach($data as $key=>$son){
/**
* 如果当前项的父节点跟上一项的id一致,
* 则说明当前项是上一节点的子节点,
* 将其存入数组中
**/
if($son['parent_id']==$fatherInfo['id']){
$this->relationship[]=$son;
// 接着找该项的子节点
$this->where_are_you_my_son($son);
}
// 注意,这里一定要是continue,不是break,否则只能找每个子节点的第一个子节点,而不是全部子节点
continue;
}
}
// 调用递归函数的方法
public function findSon($rootInfo){
$this->where_are_you_my_son($rootInfo);
return $this->relationship;
}
}
其中,
findSon()
函数的$rootInfo
就是根节点的信息,类比上面的数据结构就是:$rootInfo=[
'id'=>0,
'content'=>'根节点'
'userinfo'=>[],
'create_time'=>0,
'parent_id'=>0,
'level'=>1
];
之后就可以获取我们想要的理想数组了,其中,为了减轻后续对排序的麻烦,最好在传入操作数据之前就对其进行创建时间前后的排序,数据库的
order
功能可以很简单的实现这个需求.有了该数据结构,之后如何输出数据,那就很简单了,这里就不赘述了.
这里再插一句,我个人认为是很好的办法:
【文章评论类,数据结构与读取方法】处理复杂数据之前
先设想最终呈现结果
再来慢慢向该结果靠近