PHP带节点操作的无限分类实现方法详解

2018-09-07 22:10

阅读:396

  本文实例讲述了PHP带节点操作的无限分类实现方法。分享给大家供大家参考,具体如下:

  包含(移动多个节点;移动单个节点;删除多个节点;删除单个节点;新增节点),另附数据库表结构

  一、db sql语句

   //db used for php无限分类 create table tree( id int(10) not null primary key auto_increment, name varchar(255) not null, lft int(10) not null default 0, rgt int(10) not null default 0, status int(1) not null default 0, index lft (`lft`), index rgt (`rgt`), index status(`status`) )charset utf8; insert into tree value (null,Food,1,18,0); insert into tree value (null,Fruit,2,11,0); insert into tree value (null,Red,3,6,0); insert into tree value (null,Cherry,4,5,0); insert into tree value (null,Yellow,7,10,0); insert into tree value (null,Banana,8,9,0); insert into tree value (null,Meat,12,17,0); insert into tree value (null,Beef,13,14,0); insert into tree value (null,Pork,15,16,0);

  二、php文件

   <?php error_reporting(0); /* 1 Food 18 +------------------------------+ 2 Fruit 11 12 Meat 17 +-------------+ +------------+ 3 Red 6 7 Yellow 10 13 Beef 14 15 Pork 16 4 Cherry 5 8 Banana 9 descendants = (right – left - 1) / 2 */ /** *用于移动一个节点(包括子节点) *@param array $pdata = array(id=>主键,root=>名称) 二选一 父节点(为空时插入最大的父节点) *@param array $ndata = array(id=>主键,root=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用) *@param array $cdata = array(id=>主键,root=>名称) 二选一 当前待移动的节点 */ function move_tree_all($pdata=array(),$ndata=array(),$cdata=array()) { $cid = $cdata[id] ? intval($cdata[id]) : ; $croot = $cdata[root]; if(!$cid && !$croot) return; //需自加判断 //1、cdata不能为顶级 //2、cdata不能比$pdata等级高 $adata = get_tree_all($cdata); //获取当前移动节点的所有节点 delete_tree_all($cdata,1); //逻辑删除当前移动节点的所有节点 foreach($adata as $k => $val) { if($k != 0) { $pdata = array(root=>$val[parent]); insert_tree($pdata,,$val[name],1); } else { //first insert_tree($pdata,$ndata,$val[name],1); } } } /** *用于移动一个节点(不包括子节点) *@param array $pdata = array(id=>主键,root=>名称) 二选一 父节点(为空时插入最大的父节点) *@param array $ndata = array(id=>主键,root=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用) *@param array $cdata = array(id=>主键,root=>名称) 二选一 当前待移动的节点 */ function move_tree_item($pdata=array(),$ndata=array(),$cdata=array()) { $cid = $cdata[id] ? intval($cdata[id]) : ; $croot = $cdata[root]; if(!$cid && !$croot) return; //需自加判断 //1、cdata不能为顶级 if(!$croot) { $sql = SELECT name from tree where id = $cid; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); $croot = $row[name]; unset($sql); } delete_tree_item($cdata,1); insert_tree($pdata,$ndata,$croot,1); } /** *用于插入一个节点 *@param array $pdata = array(id=>主键,root=>名称) 二选一 父节点(为空时插入最大的父节点) *@param array $ndata = array(id=>主键,root=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用) *@param string $name string 新插入的名称 *@param int $update 默认为空,为1时更新插入 */ function insert_tree($pdata=array(),$ndata=array(),$name,$update=) { if(!$name) return; $pid = $pdata[id] ? intval($pdata[id]) : ; $proot = $pdata[root]; $nid = $ndata[id] ? intval($ndata[id]) : ; $nroot = $ndata[root]; //有父无兄(最小的子节点,父节点的最后一个儿子) if(($pid $proot) && !($nid $nroot)) { $sql = $pid ? SELECT lft, rgt FROM tree WHERE id = {$pid}; : SELECT lft, rgt FROM tree WHERE name = {$proot};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); unset($sql); //新节点 $lft = $row[rgt]; $rgt = $lft+1; if(!$update) { $sql = insert into tree values (null,{$name},$lft,$rgt,0);; $sql1 = update tree set rgt = rgt+2 where rgt >= {$row[rgt]}; $sql2 = update tree set lft = lft+2 where lft >= {$row[rgt]}; } else { $sql = update tree set lft=$lft,rgt=$rgt,status=0 where name ={$name};; $sql1 = update tree set rgt = rgt+2 where status =0 and rgt >= {$row[rgt]}; $sql2 = update tree set lft = lft+2 where status =0 and lft >= {$row[rgt]}; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql); //last add new data } //有父有兄 if(($pid $proot) && ($nid $nroot)) { $sql = $nid ? SELECT lft, rgt FROM tree WHERE id = {$nid}; : SELECT lft, rgt FROM tree WHERE name = {$nroot};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); unset($sql); //新节点 $lft = $row[lft]; $rgt = $lft+1; if(!$update) { $sql = insert into tree values (null,{$name},$lft,$rgt,0);; $sql1 = update tree set rgt = rgt+2 where rgt >= {$row[lft]};; $sql2 = update tree set lft = lft+2 where lft >= {$row[lft]};; } else { $sql = update tree set lft=$lft,rgt=$rgt,status=0 where name ={$name};; $sql1 = update tree set rgt = rgt+2 where status = 0 and rgt >= {$row[lft]};; $sql2 = update tree set lft = lft+2 where status = 0 and lft >= {$row[lft]};; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql); //last add new data } //无父无兄(大佬) if(!($pid $proot) && !($nid $nroot)) { $sql = SELECT max(`rgt`) as rgt FROM tree;; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); unset($sql); //新节点 $lft = 1; $rgt = $row[rgt]+2; if(!$update) { $sql = insert into tree values (null,{$name},$lft,$rgt,0);; $sql1 = update tree set rgt = rgt+1; $sql2 = update tree set lft = lft+1; } else { $sql = update tree set lft=$lft,rgt=$rgt,status=0 where name ={$name};; $sql1 = update tree set rgt = rgt+1 where status = 0; $sql2 = update tree set lft = lft+1 where status = 0; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql); //last add new data } } /** *用于删除一个节点(包括子节点) *@param array $data = array(id=>主键,root=>名称) 二选一 *@param int $update 默认为空,为1时逻辑删除 */ function delete_tree_all($data,$update=) { $id = $data[id] ? intval($data[id]) : ; $root = $data[root]; if(!$id && !$root) return; $sql = $id ? SELECT lft, rgt FROM tree WHERE id = {$id}; : SELECT lft, rgt FROM tree WHERE name = {$root};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); unset($sql); $middle = $row[rgt]-$row[lft]+1; if(!$update) { $sql = delete from tree where lft BETWEEN . $row[lft] . AND . $row[rgt] .; $sql1 = update tree set rgt = rgt-{$middle} where rgt > {$row[rgt]}; $sql2 = update tree set lft = lft-{$middle} where lft > {$row[rgt]}; } else { $sql = update tree set status = 1 where lft BETWEEN . $row[lft] . AND . $row[rgt] .; $sql1 = update tree set rgt = rgt-{$middle} where status=0 and rgt > {$row[rgt]}; $sql2 = update tree set lft = lft-{$middle} where status=0 and lft > {$row[rgt]}; } mysql_query($sql); mysql_query($sql1); mysql_query($sql2); } /** *用于删除一个节点(不包括子节点) *@param array $data = array(id=>主键,root=>名称) 二选一 *@param int $update 默认为空,为1时逻辑删除 */ function delete_tree_item($data,$update=) { $id = $data[id] ? intval($data[id]) : ; $root = $data[root]; if(!$id && !$root) return; $sql = $id ? SELECT id,lft, rgt FROM tree WHERE id = {$id}; : SELECT id,lft, rgt FROM tree WHERE name = {$root};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); unset($sql); if(!$update) { $sql = delete from tree where id = {$row[id]};; $sql1 = update tree set rgt = rgt-1,lft = lft -1 where lft > {$row[lft]} and rgt < {$row[rgt]}; $sql2 = update tree set lft = lft-2 where lft > {$row[rgt]}; $sql3 = update tree set rgt = rgt-2 where rgt > {$row[rgt]}; } else { $sql = update tree set status = 1 where id = {$row[id]};; $sql1 = update tree set rgt = rgt-1,lft = lft -1 where status = 0 and lft > {$row[lft]} and rgt < {$row[rgt]}; $sql2 = update tree set lft = lft-2 where status = 0 and lft > {$row[rgt]}; $sql3 = update tree set rgt = rgt-2 where status = 0 and rgt > {$row[rgt]}; } mysql_query($sql); mysql_query($sql1); //can do or not do just right,but not do load empty 2 number in middle mysql_query($sql2); mysql_query($sql3); } /** *用于获取所有的节点 *@param array $data = array(id=>主键,root=>名称) 二选一 */ function get_tree_all($data) { $id = $data[id] ? intval($data[id]) : ; $root = $data[root]; if(!$id && !$root) return; $sql = $id ? SELECT lft, rgt FROM tree WHERE id = {$id}; : SELECT lft, rgt FROM tree WHERE name = {$root};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); $adata = array(); //所有数据 $right = array(); //计数 $prev = array(); $result = mysql_query(SELECT id,name, lft, rgt FROM tree WHERE lft BETWEEN . $row[lft] . AND . $row[rgt] . ORDER BY lft ASC ;); while ($row = mysql_fetch_assoc($result)) { if (count($right) > 0) { while ($right[count($right) - 1] < $row[rgt]) { // 检查我们是否应该将节点移出堆栈 array_pop($right); array_pop($prev); } } $parent = $prev ? end($prev) : ; $adata[] = array(id=>$row[id],name=>$row[name],level=>count($right),parent=>$parent); $right[] = $row[rgt]; $prev[] = $row[name]; } return $adata; } /** *用于展示分类 *@param array $data = array(id=>主键,root=>名称) 二选一 */ function display_tree($data) { $id = $data[id] ? intval($data[id]) : ; $root = $data[root]; if(!$id && !$root) return; $sql = $id ? SELECT lft, rgt FROM tree WHERE id = {$id}; : SELECT lft, rgt FROM tree WHERE name = {$root};; $result = mysql_query($sql); $row = mysql_fetch_assoc($result); $right = array(); $result = mysql_query(SELECT name, lft, rgt FROM tree WHERE lft BETWEEN . $row[lft] . AND . $row[rgt] . ORDER BY lft ASC ;); while ($row = mysql_fetch_assoc($result)) { if (count($right) > 0) { // 检查我们是否应该将节点移出堆栈 while ($right[count($right) - 1] < $row[rgt]) { array_pop($right); } } echo str_repeat( ,count($right)) . $row[name] . \n; $right[] = $row[rgt]; } } mysql_connect(localhost,root,) or die(connect error); mysql_select_db(test) or die(database error); mysql_query(set names utf8); display_tree(array(root=>Food)); //display_tree(array(root=>bigboss)); //move_tree_all($pdata=array(root=>Fruit),$ndata=array(root=>Red),$cdata=array(root=>Meat)); //move_tree_all(,,$cdata=array(root=>Meat)); //move_tree_item(,,array(root=>Red)); //move_tree_item(array(root=>Red),array(root=>Cherry),array(root=>Fruit)); //delete_tree_all(array(root=>Yellow)); //delete_tree_all(array(root=>Meat)); //delete_tree_item(array(root=>Meat)); //insert_tree(,,bigboss); //insert_tree(array(root=>Red),,dalao); //insert_tree(array(root=>Red),array(root=>Cherry),baddalao); //insert_tree(array(root=>Fruit),array(root=>Red),Redbother); display_tree(array(root=>Food));

  更多关于PHP相关内容感兴趣的读者可查看本站专题:《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php面向对象程序设计入门教程》、《PHP网络编程技巧总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

  希望本文所述对大家PHP程序设计有所帮助。


评论


亲,登录后才可以留言!