在开发项目时,客户要求在网站的评论中增加无限回复评论的功能,作为伸手党,楼主第一时间自然是百度啦!
网上也有相关代码,基本上都是使用的递归查询方法,不过目前不通过递归似乎也没有好的办法,但是咱们得考虑性能啊,如果一条评论有1000条下级回复(一级接一级)那就得多出1000次查询,别提有多蛋疼了。
so,楼主决定自己研究,于是有了这篇文章。
在这里我们就以无限分类为例子:
首先创建数据库:
CREATE DATABASE IF NOT EXISTS `fenlei` DEFAULT character SET utf8 COLLATE utf8_general_ci;
USE `fenlei`;
CREATE TABLE IF NOT EXISTS `category` (
`catid` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`upid` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '上级分类catid',
`catname` varchar(255) NOT NULL DEFAULT '' COMMENT '分类名称',
`displayorder` tinyint(1) NOT NULL DEFAULT '0' COMMENT '显示顺序',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-关闭,1-启用',
PRIMARY KEY (`catid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文章分类';
INSERT INTO `category` VALUES
('1', '0', '分类1', '0', '1'),
('2', '0', '分类2', '0', '1'),
('3', '0', '分类3', '0', '1'),
('4', '0', '分类4', '0', '1'),
('5', '0', '分类5', '0', '1'),
('6', '1', '分类1-1', '0', '1'),
('7', '1', '分类1-2', '0', '1'),
('8', '1', '分类1-3', '0', '1'),
('9', '1', '分类1-4', '0', '1'),
('10', '1', '分类1-5', '0', '1'),
('11', '6', '分类1-1-1', '0', '1'),
('12', '6', '分类1-1-2', '0', '1'),
('13', '6', '分类1-1-3', '0', '1'),
('14', '7', '分类1-2-1', '0', '1'),
('15', '7', '分类1-2-2', '0', '1'),
('16', '11', '分类1-1-1-1', '0', '1'),
('17', '11', '分类1-1-1-2', '0', '1');
是的,你没看错,有且只有一个数据表且只有五个字段(如你有其他需要请自行扩展,在此我只列出有用的字段)
接下来开始大动作,先直接上类:
<?php
/*
* 这是一个成熟的模型,放入相应文件夹直接调用即可
*/
namespace appindexmodel;
class Category extends hinkModel
{
/*
* 打开冰箱:从数据库取出所有数据,并放进缓存内
* 即可独立输出也可以在其他位置调用
*/
public function category_query($catid=0)
{
cache('category',null);//正式环境删除本行可减少一次查询
if(!$result = cache('category')){
$Category = new Category();
$result = [];
foreach($Category->order('displayorder asc,catid asc')->select() as $data){
$result[$data['catid']] = $data;
}
cache('category',$result,0);
}
return $catid ? $result[$catid] : $result;//如果传入单个分类catid,那么直接返回就行,可用于列表页,大大降低查询次数
}
/*
* 把大象放进冰箱:将第一步得到的数据集转化为无限级数组
* 即可独立输出也可以在其他位置调用
*/
public function category_tree($upid=0,$status='0,1'){
$status = is_string($status) ? explode(',', $status) : $status;
$result = [];
foreach($this->category_query() as $catid=>$cat){
if($upid == $cat['upid'] && in_array($cat['status'],$status)){
$cat['subcat'] = $this->category_tree($cat['catid'],$status);
$result[] = $cat;
}
}
return $result;
}
/*
* 关上冰箱门:用于实际用途,将多级数据传入,转化为前端html代码
* 该html的转化结果可从第一步中获取方式不同来实现从哪一级开始展示
* 本函数只是师范函数,实际运用中只需要修改这个函数结构体就能完全实现仿网易盖楼效果
*/
public function category_html($categorys,$depth=0){
$depth_html = $html = '';
for ($i=0; $i < $depth; $i++) {
$depth_html .= '——';
}
foreach($categorys as $data){
$html .= '<tr>';
$html .= '<td class="center">'.$data['catid'].'</td class="center">';
$html .= '<td class="center">'.$data['displayorder'].'</td>';
$html .= '<td>'.$depth_html.$data['catname'].'</td>';
$html .= '</tr>';
if($data['subcat']){
$html .= $this->category_html($data['subcat'],$depth+1);
}
}
return $html;
}
}
?>
首先通过category_query方法获取到所有分类,
然后通过category_tree方法将得到的数据转化为无限分类数组
最后再通过category_html方法将上面得到的无限分类数组输出为html
最后在控制器中使用
<?php
namespace appindexcontroller;
use thinkController;
use appindexmodelCategory;//引入模型类
class Index extends Controller
{
public function index()
{
$Category = new Category;//实例化类
$category_tree = $Category->category_tree();// 获取整体多级数组树结果
$this->view->category_list = $Category->category_html($category_tree);//将结果转化为实体html并传值给模板
return $this->fetch();
}
}
来调用输出数据,最终结果如下:
最后再说说本方法的优势吧:
一、数据只用查询一次,无论你有多少级分类,都只需查询一次。
二、查询的数组结果和无限分类结果是独立方法,你可以直接通过方法调用来获取最终结果
三、无限分类html输出结果可以通过函数自定义