文章评论类,数据结构与读取方法

今天刚交付了一个项目,其中一项功能是自由评论,就是可以针对一篇文章在评论区,针对任意位置进行插入评论,类似于Laravel官网的评论区一样的功能:

文章评论类,数据结构与读取方法_第1张图片

其中可以针对任何一个人进行回复.说白一点就是多叉树,类似的结构如下:

文章评论类,数据结构与读取方法_第2张图片

文章的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=[
        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=$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功能可以很简单的实现这个需求.

有了该数据结构,之后如何输出数据,那就很简单了,这里就不赘述了.

这里再插一句,我个人认为是很好的办法:

处理复杂数据之前
先设想最终呈现结果
再来慢慢向该结果靠近

你可能感兴趣的:(实战)