那么我们怎样才能通过一个SQL语句把所有的分类都查询出来呢,而且要求如果是子类的话前面要打几个空格以表现是子分类。要想查询出所有分类很好办:
SELECT * FROM category WHERE lft>1 AND lft<18 ORDER BY lft
这样的话所有的分类都出来了,但是谁是谁的子类却分不清,那么怎么办呢?我们仔细看图不难发现如果相邻的两条记录的右值第一条的右值比第二条的大那么就是他的父类,比如food的右值是18而fruit的右值是11 那么food是fruit的父类,但是又要考虑到多级目录。于是有了这样的设计,我们用一个数组来存储上一条记录的右值,再把它和本条记录的右值比较,如果前者比后者小,说明不是父子关系,就用array_pop弹出数组,否则就保留,之后根据数组的大小来打印空格。这样就解决了这个问题。代码如下
表结构:
--
-- 表的结构 `category`
--
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '1为文章类型2为产品类型3为下载类型',
`title` varchar(50) NOT NULL,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
`lorder` int(11) NOT NULL COMMENT '排序',
`create_time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- 导出表中的数据 `category`
--
INSERT INTO `category` (`id`, `type`, `title`, `lft`, `rgt`, `lorder`, `create_time`) VALUES
(1, 1, '优异栏目', 1, 18, 1, 1261964806),
(2, 1, '公司简介', 14, 17, 50, 1264586212),
(3, 1, '新闻', 12, 13, 50, 1264586226),
(4, 2, '公司产品', 10, 11, 50, 1264586249),
(5, 1, '荣誉资质', 8, 9, 50, 1264586270),
(6, 3, '资料下载', 6, 7, 50, 1264586295),
(7, 1, '人才招聘', 4, 5, 50, 1264586314),
(8, 1, '留言板', 2, 3, 50, 1264586884),
(9, 1, '总裁', 15, 16, 50, 1267771951);
/**
* 显示树,把所有的节点都显示出来。
* 1、先得到根结点的左右值(默认根节点的title为“优异目录”)。
* 2、查询左右值在根节点的左右值范围内的记录,并且根据左值排序。
* 3、如果本次记录右值大于前次记录的右值则为子分类,输出时候加空格。
* @return array
**/
function display_tree(){
//获得root左边和右边的值
$arr_lr = $this->category->where("title = '优异栏目'")->find();
//print_r($arr_lr);
if($arr_lr){
$right = array();
$arr_tree = $this->category->query("SELECT id, type, title, rgt FROM category WHERE lft >= ". $arr_lr['lft'] ." AND lft <=".$arr_lr['rgt']." ORDER BY lft");
foreach($arr_tree as $v){
if(count($right)){
while ($right[count($right) -1] < $v['rgt']){
array_pop($right);
}
}
$title = $v['title'];
if(count($right)){
$title = '|-'.$title;
}
$arr_list[] = array('id' => $v['id'], 'type' => $type, 'title' => str_repeat(' ', count($right)).$title, 'name' =>$v['title']);
$right[] = $v['rgt'];
}
return $arr_list;
}
}
-- 表的结构 `category`
--
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '1为文章类型2为产品类型3为下载类型',
`title` varchar(50) NOT NULL,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
`lorder` int(11) NOT NULL COMMENT '排序',
`create_time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- 导出表中的数据 `category`
--
INSERT INTO `category` (`id`, `type`, `title`, `lft`, `rgt`, `lorder`, `create_time`) VALUES
(1, 1, '优异栏目', 1, 18, 1, 1261964806),
(2, 1, '公司简介', 14, 17, 50, 1264586212),
(3, 1, '新闻', 12, 13, 50, 1264586226),
(4, 2, '公司产品', 10, 11, 50, 1264586249),
(5, 1, '荣誉资质', 8, 9, 50, 1264586270),
(6, 3, '资料下载', 6, 7, 50, 1264586295),
(7, 1, '人才招聘', 4, 5, 50, 1264586314),
(8, 1, '留言板', 2, 3, 50, 1264586884),
(9, 1, '总裁', 15, 16, 50, 1267771951);
/**
* 显示树,把所有的节点都显示出来。
* 1、先得到根结点的左右值(默认根节点的title为“优异目录”)。
* 2、查询左右值在根节点的左右值范围内的记录,并且根据左值排序。
* 3、如果本次记录右值大于前次记录的右值则为子分类,输出时候加空格。
* @return array
**/
function display_tree(){
//获得root左边和右边的值
$arr_lr = $this->category->where("title = '优异栏目'")->find();
//print_r($arr_lr);
if($arr_lr){
$right = array();
$arr_tree = $this->category->query("SELECT id, type, title, rgt FROM category WHERE lft >= ". $arr_lr['lft'] ." AND lft <=".$arr_lr['rgt']." ORDER BY lft");
foreach($arr_tree as $v){
if(count($right)){
while ($right[count($right) -1] < $v['rgt']){
array_pop($right);
}
}
$title = $v['title'];
if(count($right)){
$title = '|-'.$title;
}
$arr_list[] = array('id' => $v['id'], 'type' => $type, 'title' => str_repeat(' ', count($right)).$title, 'name' =>$v['title']);
$right[] = $v['rgt'];
}
return $arr_list;
}
}