PHP:打造一个无限极评论模块

我的毕设项目的评论模块原来是采用多说插件完成的,但是我现在希望能够自己管理评论内容,所以自己开始写评论模块。具体准备采用与简书下评论类似的结构,即一级评论直接显示在文章下方,而二三级评论显示在一级评论的下方,如下图所示:

评论结构

我觉得这可以说是无限极分类的一种运用,准确的说是子孙树的运用,进行子孙树分类后,循环输出内容,形成评论(不懂无限极分类的朋友可以去看看我的文章无限极分类原理与实现)。

当然,真正完成无限极回复评论的功能还有其他的要点,下面就来说说我是怎么完成无限极评论的。

数据库设计

首先,就是数据表的设计。如果是论坛系统,可以将评论的数据分割成两个表,一个表存储评论的信息,包括发布帖子的用户id或回复的用户id回复的帖子id回复的时间等;另一个表,存储评论的内容,包括帖子的主题和回复的内容。

我完成的是文章的评论模块,就没分成两个表了,直接将评论的内容与信息放在一起,如下面结构:

| 列名 | 列类型 | 列属性 | 说明 |
|------|--------|------- |
| comm_id| INT | UNSIGNED PRIMARY KEY AUTO_INCREMENT | 主键
| user_id | INT | UNSIGNED NOT NULL DEFAULT 0 | 用户id
| parent_id | INT |UNSIGNED NOT NULL DEFAULT 0| 评论的父级
| artcile_id | INT |UNSIGNED NOT NULL DEFAULT 0| 评论的文章id
| comm_cont | TEXT | | 评论的内容
| comm_time | INT | UNSIGNED NOT NULL DEFAULT 0 | 评论发布的时间

SQL语句:

CREATE TABLE comment (
    comm_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    user_id INT UNSIGNED NOT NULL DEFAULT 0 ,
    parent_id INT UNSIGNED NOT NULL DEFAULT 0 ,
    article_id INT UNSIGNED NOT NULL DEFAULT 0 ,
    comm_cont TEXT,
    comm_time INT UNSIGNED NOT NULL DEFAULT 0 
) ENGINE=MYISAM CHARSET=UTF8 ;

这种结构是完成无限极回复的基础,也能够很明显的看出取出的数据能很好的进行无限极分类。

评论的结构分析

完成一个评论模块是很容易的,评论放入数据库,然后取回放置在html中,同样能完成评论模块。但是,这种结构是很杂乱,无序的。要想完成如简书评论一样的评论模块,就得采用特殊的方式。

那么,就要好好观察一下简书评论的结构了。

评论结构

结合上面的数据表结构,可以推断一下,从数据表中取出且无限极分类后的数据,它的结构应该是这样的:

array (
    array(一级评论,
        child=>array(
            二级评论,
            三级评论
            )
        ),
    array (
        一级评论 ,
        child=>array(
            )
    ……

为什么这么说?你可以很明显的看出,二级、三级评论被包裹在一级评论中,而二级、三级评论是平行关系;因此,二级、三级评论是一级评论的子孙节点,而二级、三级评论是平行节点,不存在父子关系。

因此,可以得出,分类后的数据有且只有一个子孙节点,多级评论无论是不是对一级评论进行回复,只要是处于一级评论的范围,那么它的父节点必然是一级评论。

那么,二级、三级回复中的@某某某又是怎么实现的?其实,我在这里困扰了很长时间。我期望用对表的自身连接来完成,但是不行,破坏了上面所述的结构。最后,我从简书请求的json数据中得到了答案,请看简书评论的json数据:

JSON数据

上传后有点模糊,各位同学可以借助火狐或者谷歌浏览器上面的插件观察JSON数据。

重点观察compiled_content字段,可以推断它是将@某某某直接存储到数据库中的。这样问题就解决了,同时观察json数据,也能够验证我上面所述的结构是正确的。

具体实现

分析完结构就来说说具体怎么来完成无限极回复。第一步,一级评论形成,这个简单,直接将评论存储即可

一级评论

而二级评论要利用到js,点击评论时,获取一级评论的用户名,并保存,在发布回复时注意将其和评论的内容结合在一起发往后台:

二级评论
// replyUser 即 被回复的用户名 @xxxx
var content = $('#reply').val.split(replyUser)[1];
var userlink = '<a href="#" class="xxx" target="_blank" >' + replyUser + '</a>';
var comm_cont = encodeURIComponent(userlink+content);

那么在数据库中表现如下:

数据表内容

之后就是一个关键点,利用子孙树进行分类,分类函数如下:

/**
 * @param $data array  数据
 * @param $parent  string 父级元素的名称 如 parent_id
 * @param $son     string 子级元素的名称 如 comm_id
 * @param $pid     int    父级元素的id 实际上传递元素的主键
 * @return array 
 */
function getSubTree($data , $parent , $son , $pid = 0) {
    $tmp = array();
    foreach ($data as $key => $value) {
        if($value[$parent] == $pid) {
            $value['child'] =  getSubTree($data , $parent , $son , $value[$son]);
            $tmp[] = $value;            
        }
    }
    return $tmp;
}

如此分类后,数据结构发生变化,大致如下:

分类后数据

拥有这种结构就能很好去完成评论了,如下

<?php foreach($tree as $key=>$val) ?>
<div class="comm_list" >
    <h2><?php echo $val['user_name'];?></h2>
    <p><?php echo $val['comm_cont'] ?></p>
    <!-- 其他信息 -->
    <div class="comm_reply">
        <?php if(!empty($val['child'])) { ?>
        <?php foreach($val['child'] as $k=>$v) ?>
        <div class="reply_list" >
            <h2><?php echo $v['user_name'];?></h2>
            <p><?php echo $v['comm_cont'] ?></p>
            <!-- 其他信息 -->
        </div>
        <?php }}?>
    </div>
</div>
<?php } ?>

同时,形成的回复样式如下所示:

snipaste20170105_204906.png

这样类简书评论结构的无限极回复就完成了。

PS

这只是评论的一种形式,如还有一种类楼梯式的结构,这种实现则更为简单一点,如下图:

楼梯式评论结构

这种结构就很容易完成,只要存储数据库中的parent_id完全等于你回复的comm_id,在经过如下无限极分类,就能够完成。

/**
 * 子孙树
 */
function getSubTree($data , $parent , $son , $pid = 0, $lev = 0) {
    $tmp = array();
    foreach ($data as $key => $value) {
        if($value[$parent] == $pid) {
            $value['lev'] = $lev;
            $tmp[] = $value;
            $tmp = array_merge($tmp , getSonTree($data , $parent , $son , $value[$son] , $lev+1));
        }
    }
    return $tmp;
}

这种无限极子孙树分类和前面给出的子孙树分类不同,分类后不会将子类包裹在child中,而是形成等级,最高级为0,依次往下。

例如:一级评论的comm_id=1,parent_id=0,那么二级评论的comm_id=2,parent_id=1;三级评论的comm_id=3,parent_id=2;

分类最后形成如下结构

array(
array('comm_id'=>1,parent_id=>0,art_id=>1,'lev'=>0) ,
array('comm_id'=>2,parent_id=>1,art_id=>1,'lev'=>1),
array('comm_id'=>3,parent_id=>2,art_id=>1,'lev'=>2),
array('comm_id'=>4,parent_id=>3,art_id=>1,'lev'=>3),
array('comm_id'=>5,parent_id=>2,art_id=>1,'lev'=>2)
);

然后直接循环输出,并将lev作为属性打印在html中,最后利用js读取lev,并根据不同的等级分配不同的margin-left即可,它会随着margin的不同而排列在不同的位置,如下:

// html中
<?php foreach($tree as $key=>$val) {?>
<div class="comm_list" lev="<?php echo $val['lev']?>">
……
</div>
<?php } ?>

// js中
$('div.comm_list').css('margin-left' , 20 * lev);

END

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容