Discuz! 嵌套回复实现
最近支援一个项目,采用discuz!程序,需要实现嵌套回复,效果类似WordPress的效果,某条回复的回复需要排在一起显示。
没有使用discuz!的点评功能,而是通过改造post表实现嵌套功能。
数据库结构
在discuz!的post表增加字段:
alter table pre_forum_post add parentid int(10) unsigned NOT NULL DEFAULT '0',topid int(10) unsigned NOT NULL DEFAULT '0';
- parentid 父级回复id
- topid 根回复id
添加回复
- 需要传递父级回复pid.
- 如果是根回复,parentid = 0,topid = 0.
- 如果是子回复,parentid = 父级回复的pid,topid = 父级回复的topid. 父级回复的pid和topid需要根据传递的pid进行查询.
查询一个回复下的所有嵌套回复
取一个根回复下的所有子回复,执行sql:
select * from pre_forum_post where toppid = xxx order by qpid desc, pid desc;
php处理成树形结构。
// $rows 为执行上述sql的查询结果 foreach ($rows as $k => $row) { if ($row['toppid'] == $row['parentid']) { $key = $row['parentid'] . '-' . $row['pid']; } else { $key = $map[$row['parentid']] . '-'. $row['pid']; } $map[$k] = $key; } ksort($map); // 排序后的结果: // 1 // 1-4 // 1-4-7 // 1-5 // 1-2 foreach ($map as $pid) { $result[$pid] = $rows[$pid]; } // result 即为排序好后的回复列表
缓存
- 对所有topid的嵌套回复建立缓存。
pid => array(), array()中存储其下所有嵌套回复。
- 列表页直接查询缓存显示。
缺点
- 更新时触发缓存更新,需要一次取出topid下的所有回复进行php排序处理。
- 回复过多时,缓存过大或无法缓存。
其他
- 因为项目需求特殊,一条回复的嵌套回复只显示前50条,所以缓存不会太大。上面这种方案应该可以满足需求,但是需要考虑查询如何优化。
- 网上搜索了相关的资料,也没有找到太合适的方案。网上的方案是取出数据后进行递归遍历,后续比较下两种方式的效率差别。
参考资料
- 无限分类设计方案 http://www.ccvita.com/315.html
- 在数据库中存储层次数据 http://shiningray.cn/hierarchical-data-database.html
我跟你的思路一样的数据库加了两个字段,我的问题是dz的源代码,和模板你怎么修改的啊,能否把你修改dz的文件发到我邮箱啊
前端已经不是用discuz模板实现了,最简单的就是按discuz模板一样一条一条回复的展示,如果需要显示嵌套效果,可以参考wordPress模板吧
请问后台数据库是递归查询的吗
一次性查出所有评论,然后PHP进行排序。
这个问题解决了,我遇到一个新的问题,做的一个插件回复帖子,有时候会出现通过插件的url回的帖子,插入post表了,但是论坛没显示,然后再通过dz的正常回复帖子回复后,然后就正常显示了
你试试直接往post表添加一条记录,论坛前台会显示出来吗?
感觉可能是少写了其他表了
能否提供下升级包?
不太熟悉这些操作,谢谢
id topid parentid
4 1 1
7 1 4
我怎么觉得你代码写的有问题
哪里呢?
$rows[$row['parentid']]这里取的是什么鬼 我请问 $rows是所有子回复的列表集合哦 按你的sql语句写的
如果拿 4 1 1这条记录来说的话 if ($row['topid']) {
$key = (string)$row['pid'];
} else {
$key = $rows[$row['parentid']] . '-' . $row['pid']; // 1-4, 1-4-7
}
$map[$key] = $row['pid'];
这条记录的运行结果是$map[4]=4;
这是对的么,还是我老花
思路就是按toppid - parentid - pid 拼数组key,然后通过php进行数组排序实现的。
为了你这个回复我又特意去看了眼这项目的代码,已经修改了。