下图是显示效果,可以单独回复某个人,并在主评论下盖楼。
YZMCMS在评论上可能是为了照顾小白用户,回复的评论是通过 截取原评论 再组合 新评论 形成一个新的评论。
大家看下表图中的数据库结构。最后的reply字段为0的评论是一级评论。reply不为0的都是回复评论。通过content字段就可以看出ID4的数据是一级评论,ID5、ID7的数据为二级评论,ID6、ID8为三级评论。回复的评论都会截取原评论里的数据。会有很多重复的数据。
但今天我们讲的不是重复数据的问题,通过上表分析,我们就可以看出,想要做评论盖楼的显示效果是非常难的。难在哪呢?难的地方就在于 子回复评论找上一级评论容易,但再找上上一级评论就不容易了,不好归类。比如:ID5的上一级评论是ID4,这个还是简单的,我们根据reply查找上一级ID就可以。但是你看看,ID6的上一级是ID5,ID5不是一级评论,它上面还有ID4。这还好只是二三级。如果是两个人在那里对话怎么办呢?就比如:ID7回复ID4,ID8回复ID7,ID9回复ID8,ID10回复ID9,ID11回复ID10。一级一级循环。没办法用语言写啊,因为数据库中少了一个一级评论的字段。没办法定位父评论。解决的办法也很简单,只要加一个父评论ID的字段,再根据ID排序就可以显示出盖楼效果。
但我们不是源代码的作者啊,不是袁总,我们随便加字段,以后更新版本就会很麻烦。
于是我想了很多天,差点都要放弃了,最后终于还是解决了。只是效率就不知道了。最好的方法终究还是等袁总添加字段的好。
下面是我的代码:
<?php $where = '`commentid` = "'.$modelid.'_'.$catid.'_'.$id.'" AND `status` = 1'; $data=D('comment')->field('id,userid,username,userpic,inputtime,content,reply')->where($where)->order('id DESC')->limit(20)->select(); $data1=$data; asort($data1);//按照数组的值升序重新排序 $a1=$a2=$ww=$zsz=array(); foreach($data as $v){ $a1[]=$v['id']; $a2[]=$v['reply']; } /* 已经废弃的代码 $w=array_combine($a1,$a2);$kg=false; foreach($a2 as $s => $v){ if(count($ww)){ foreach($ww as $s1 => $v1){ if($s1==$v){ $kg=true; array_push($ww[$s1],$a1[$s]); break; } } if(!$kg){ $ww[$v]=array($a1[$s]); } $kg=false; }else{ $ww[$v]=array($a1[$s]); } } */ foreach($a2 as $s => $v){ //根据reply的值 合并评论层级 $ww[$v][]=$a1[$s]; } ksort($ww);//按照数组键名升序重新排序 $wy=$ww; foreach($ww as $s => $v){ if(!$s) unset($wy[0]); //去掉变量$wy的0级的评论 if($s){ if(count($wy)>1) unset($wy[$s]); //$wy数组大于1个时,去掉$wy[$s],用剩余的数组循环 foreach($wy as $s1 => $v1){ if(in_array($s1, $zsz)) break; //检查子评论ID在不在数组中,已经合并到父评论的不参加循环 if(in_array($s1, $v)){ $v=$ww[$s]=array_merge_recursive($v,$v1); //将子评论合并到各自的父评论中 array_push($zsz,$s1);//将子评论的键名key加入到数组中 continue; } } } } for($i=0; $i<count($zsz); ++$i) //删除数组中重复的一级数组 { unset($ww[$zsz[$i]]); } ?> {loop $data $v} {if isset($ww[0])}{if in_array($v['id'], $ww[0])} <li class="entry"> <!--这里是父评论输出--> {/if}{/if} {if isset($ww[$v['id']])} <ul class="reply"> {php $js=0;} {loop $data1 $s1=>$v1} {if in_array($v1['id'], $ww[$v['id']])} <!--这里是循环输出子评论> {/if} {/loop} </ul> {/if} {if isset($ww[0])}{if in_array($v['id'], $ww[0])} </li> {/if}{/if} {/loop} {if empty($data)}<!-- 还没有评论,快来抢沙发吧!-->{/if} {php unset($a1,$a2,$ww,$wy,$zsz,$data);}
好了,上面就是运行的代码,具体的可以去演示站查看 点这里去演示站看 。
这个模板代码是免费的,也可以下载去看看。点这里传送。