萬盛學電腦網

 萬盛學電腦網 >> 數據庫 >> mysql教程 >> php mysql無限級分類實現原理與代碼

php mysql無限級分類實現原理與代碼

表結構:
復制代碼 代碼如下:
--
-- 表的結構 `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;
}
}

好了 只要這樣所有的分類都可以一次性查詢出來了,而不用通過遞歸了。
下面的問題是怎樣進行插入、刪除和修改操作
插入:插入操作很簡單找到其父節點,之後把左值和右值大於父節點左值的節點的左右值加上2,之後再插入本節點,左右值分別為父節點左值加一和加二,可以用一個存儲過程來操作:
復制代碼 代碼如下:
CREATE PROCEDURE `category_insert_by_parent`(IN pid INT,IN title VARCHAR(20), IN type INT, IN l_order INT, IN pubtime INT)
BEGIN
DECLARE myLeft INT;
SELECT lft into myLeft FROM category WHERE id= pid;
UPDATE qy_category SET rgt = rgt + 2 WHERE rgt > myLeft;
UPDATE qy_category SET lft = lft + 2 WHERE lft > myLeft;
INSERT INTO qy_category(type, title, lft, rgt, lorder, create_time) VALUES(type ,title, myLeft + 1, myLeft + 2, l_order, pubtime);
commit;
END

刪除操作:
刪除的原理:1.得到要刪除節點的左右值,並得到他們的差再加一,@mywidth = @rgt - @lft + 1;
2.刪除左右值在本節點之間的節點
3.修改條件為大於本節點右值的所有節點,操作為把他們的左右值都減去@mywidth
存儲過程如下:
復制代碼 代碼如下:
CREATE PROCEDURE `category_delete_by_key`(IN id INT)
BEGIN
SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM category
WHERE id = id;
DELETE FROM category WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;

修改:
要命的修改操作,本人看了很久也沒有看出什麼規律出來,只要出此下策,先刪除再插入,只要調用上面2個存儲過程就可以了!
總結:查詢方便,但是增刪改操作有點繁瑣,但是一般分類此類操作不是很多,還是查詢用的多,再說弄個存儲過程也方便!

copyright © 萬盛學電腦網 all rights reserved