PHP:打造一個無限極評論模組

來源:互聯網
上載者:User
我的畢設項目的評論模組原來是採用多說外掛程式完成的,但是我現在希望能夠自己管理評論內容,所以自己開始寫評論模組。具體準備採用與下評論類似的結構,即一級評論直接顯示在文章下方,而二三級評論顯示在一級評論的下方,如所示:


評論結構

我覺得這可以說是無限極分類的一種運用,準確的說是子孫樹的運用,進行子孫樹分類後,迴圈輸出內容,形成評論(不懂無限極分類的朋友可以去看看我的文章無限極分類原理與實現)。

當然,真正完成無限極回複評論的功能還有其他的要點,下面就來說說我是怎麼完成無限極評論的。

資料庫設計

首先,就是資料表的設計。如果是論壇系統,可以將評論的資料分割成兩個表,一個表格儲存體評論的資訊,包括發布文章的使用者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資料

上傳後有點模糊,各位同學可以藉助Firefox或者Google瀏覽器上面的外掛程式觀察JSON資料。

重點觀察compiled_content欄位,可以推斷它是將@某某某直接儲存到資料庫中的。這樣問題就解決了,同時觀察json資料,也能夠驗證我上面所述的結構是正確的。

具體實現

分析完結構就來說說具體怎麼來完成無限極回複。第一步,一級評論形成,這個簡單,直接將評論儲存即可


一級評論

而二級評論要利用到js,點擊評論時,擷取一級評論的使用者名稱,並儲存,在發布回複時注意將其和評論的內容結合在一起發往後台:


二級評論

// replyUser 即 被回複的使用者名稱 @xxxxvar 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) ?><p class="comm_list" >    <h2><?php echo $val['user_name'];?></h2>    <p><?php echo $val['comm_cont'] ?></p>    <!-- 其他資訊 -->    <p class="comm_reply">        <?php if(!empty($val['child'])) { ?>        <?php foreach($val['child'] as $k=>$v) ?>        <p class="reply_list" >            <h2><?php echo $v['user_name'];?></h2>            <p><?php echo $v['comm_cont'] ?></p>            <!-- 其他資訊 -->        </p>        <?php }}?>    </p></p><?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) {?><p class="comm_list" lev="<?php echo $val['lev']?>">……</p><?php } ?>// js中$('p.comm_list').css('margin-left' , 20 * lev);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.