ThinkPHP结合Jquery实现无限级嵌套回复
blog程序出来这么久,一直为文章的嵌套回复困恼。主要由于ThinkPHP模板的缘故,无法使用PHP语言在页面直接生成嵌套内容。经过不断的度娘爬文,找到了个思路。
思路大概是,先从数据库中读取文章的所有回复,在ThinkPHP中对数组计算,形成一个树形结构。
以下是数据库结构:

每一条记录通过reply字段,跟他的父项目建立关联。使用递归的方法将子项加入父项目,直到最底层介绍,重新整理后通过JSON输出整个回复的树形结构。
以下为ThinkPHP处理回复的函数
/*返回经过处理过后Json,完成回复嵌套*/
public function findParentNode($array, $children, $parentId) {
$length = sizeof($array);
for ($i = 0; $i < $length; $i++) {
if ($array[$i]['id'] == $parentId) {
if ($array[$i]['children'] == NULL) {
$array[$i]['children'] = array($children);
//给每个有子项的父项加入一个children字段
} else {
array_push($array[$i]['children'], $children);
}
return $array;
}
if (!empty($array)) {
$array[$i]['children'] = $this->findParentNode($array[$i]['children'], $children, $parentId);
//递归调用往下一层级遍历
}
}
return $array;
}
/*$id:文章id*/
public function getCommentsJson($id) {
$model = M('comments');
$array = $model->where('archive=' . $id)->order('id asc')->select();
foreach ($array as $key => $value) {
$value["children"] = 'children';
$array[$key]['email'] = getGravatar($array[$key]['email']);
$array[$key]['children'] = array();
if ($value["reply"] != '0') {
//判断是否为父项
$array_children = $array[$key];
$array = $this->findParentNode($array, $array_children, $value["reply"]); //将有子项的回复代入findParentNode
}
}
//重新整理,讲数组根目录下,删除replyID的元素
$rtnArray = array();
$l = sizeof($array);
for ($i = 0; $i < $l; $i++) {
if ($array[$i]['reply'] == '0') {
array_push($rtnArray, $array[$i]);
}
}
print_r(json_encode($rtnArray));
}
/*****************嵌套回复测试片段*****************************/在前台模板中通过ajax请求ThinkPHP函数地址,并对json进行遍历根据层级输出。
comment.js
/*每条comment回复模板*/
var liTemplate = "<li class=\"comment-body comment-odd \" id=\"comment-{#commentId#}\" itemscope=\"\"><div class=\"comment-author\" itemprop=\"creator\"><span itemprop=\"image\"><img width=\"32\" height=\"32\" class=\"avatar\" alt=\"{#commentAuthor#}\" src=\"{#commentEmail#}\"></span><cite class=\"fn\" itemprop=\"name\"><a href=\"#\" id=\"author-41\" rel=\"external nofollow\">{#commentAuthor#}</a></cite></div><div class=\"comment-meta\"><a href=\"#comment-{#commentReply#}\"><time itemprop=\"commentTime\">{#commentTime#}</time></a></div><div class=\"comment-content\" itemprop=\"commentText\"><p>{#commentTxt#}</p></div><div class=\"comment-reply-{#commentId#}\"><a onclick=\"typechoCommentChild({#commentId#})\" href=\"#respond-post-1\" rel=\"nofollow\">回复</a></div></li>";
//获取js文件调用参数
var archiveId = document.getElementById('commentScript').getAttribute('archiveId');
var urlRoot = document.getElementById('commentScript').getAttribute('url');
function display(obj, dom, level) {
var i = 0;
var ol = $('<ol/>');
ol.addClass('comment-list comment-main');
while (i < obj.length) {
var commentStr = liTemplate;
//替换掉模板中的信息
commentStr = commentStr.replace(/{#commentId#}/g, obj[i]['id']);
commentStr = commentStr.replace(/{#commentAuthor#}/g, obj[i]['author']);
commentStr = commentStr.replace('{#commentTxt#}', obj[i]['comment']);
commentStr = commentStr.replace('{#commentEmail#}', obj[i]['email']);
commentStr = commentStr.replace(/{#commentTime#}/g, obj[i]['commtime']);
commentStr = commentStr.replace(/{#commentReply#}/g, obj[i]['reply']);
var dom_children = $(commentStr);
if (level % 2 == 1) {//判断奇偶根据奇偶设置每个层级的class
dom_children.addClass('comment-level-odd');
} else {
dom_children.addClass('comment-level-even');
}
ol.addClass('comment-parent-' + obj[i]['reply']);
ol.append(dom_children);
var childrenNode = obj[i]['children'];
if (childrenNode != null) {
level++;
display(childrenNode, dom_children, level);
level--;
}
if (childrenNode == null && i == obj.length - 1) {
return;
}
i++;
}
if (level != 0) {//判断是否为根节点
ol.removeClass('comment-main');
var div = $('<div/>');
div.addClass('comment-children');
div.append(ol);
ol = div;
}
dom.append(ol);
}
$.ajax({
type: 'get',
url: urlRoot + '/index.php/home/index/getcommentsjson/id/' + archiveId,
datatype: 'json',
data: {},
success: function(data1) {
var obj = eval('(' + data1 + ')');
var dom = $('#comments');
display(obj, dom, false);
}
});具体实现效果请看本文回复。
有19条评论