PHP带节点操作的无限分类实现方法详解
本文实例讲述了PHP带节点操作的无限分类实现方法。分享给大家供大家参考,具体如下:
包含(移动多个节点;移动单个节点;删除多个节点;删除单个节点;新增节点),另附数据库表结构
一、dbsql语句
//dbusedforphp无限分类 createtabletree( idint(10)notnullprimarykeyauto_increment, namevarchar(255)notnull, lftint(10)notnulldefault0, rgtint(10)notnulldefault0, statusint(1)notnulldefault0, indexlft(`lft`), indexrgt(`rgt`), indexstatus(`status`) )charsetutf8; insertintotreevalue(null,'Food',1,18,0); insertintotreevalue(null,'Fruit',2,11,0); insertintotreevalue(null,'Red',3,6,0); insertintotreevalue(null,'Cherry',4,5,0); insertintotreevalue(null,'Yellow',7,10,0); insertintotreevalue(null,'Banana',8,9,0); insertintotreevalue(null,'Meat',12,17,0); insertintotreevalue(null,'Beef',13,14,0); insertintotreevalue(null,'Pork',15,16,0);
二、php文件
<?php error_reporting(0); /* 1Food18 +------------------------------+ 2Fruit1112Meat17 +-------------++------------+ 3Red67Yellow1013Beef1415Pork16 4Cherry58Banana9 descendants=(right–left-1)/2 */ /** *用于移动一个节点(包括子节点) *@paramarray$pdata=array('id'=>主键,'root'=>名称)二选一父节点(为空时插入最大的父节点) *@paramarray$ndata=array('id'=>主键,'root'=>名称)二选一下一个兄弟节点(没有兄弟的时候就不用) *@paramarray$cdata=array('id'=>主键,'root'=>名称)二选一当前待移动的节点 */ functionmove_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($adataas$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); } } } /** *用于移动一个节点(不包括子节点) *@paramarray$pdata=array('id'=>主键,'root'=>名称)二选一父节点(为空时插入最大的父节点) *@paramarray$ndata=array('id'=>主键,'root'=>名称)二选一下一个兄弟节点(没有兄弟的时候就不用) *@paramarray$cdata=array('id'=>主键,'root'=>名称)二选一当前待移动的节点 */ functionmove_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="SELECTnamefromtreewhereid=$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); } /** *用于插入一个节点 *@paramarray$pdata=array('id'=>主键,'root'=>名称)二选一父节点(为空时插入最大的父节点) *@paramarray$ndata=array('id'=>主键,'root'=>名称)二选一下一个兄弟节点(没有兄弟的时候就不用) *@paramstring$namestring新插入的名称 *@paramint$update默认为空,为1时更新插入 */ functioninsert_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?"SELECTlft,rgtFROMtreeWHEREid='{$pid}';":"SELECTlft,rgtFROMtreeWHEREname='{$proot}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); unset($sql); //新节点 $lft=$row['rgt']; $rgt=$lft+1; if(!$update){ $sql="insertintotreevalues(null,'{$name}',$lft,$rgt,0);"; $sql1="updatetreesetrgt=rgt+2wherergt>={$row['rgt']}"; $sql2="updatetreesetlft=lft+2wherelft>={$row['rgt']}"; }else{ $sql="updatetreesetlft=$lft,rgt=$rgt,status=0wherename='{$name}';"; $sql1="updatetreesetrgt=rgt+2wherestatus=0andrgt>={$row['rgt']}"; $sql2="updatetreesetlft=lft+2wherestatus=0andlft>={$row['rgt']}"; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql);//lastaddnewdata } //有父有兄 if(($pid||$proot)&&($nid||$nroot)){ $sql=$nid?"SELECTlft,rgtFROMtreeWHEREid='{$nid}';":"SELECTlft,rgtFROMtreeWHEREname='{$nroot}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); unset($sql); //新节点 $lft=$row['lft']; $rgt=$lft+1; if(!$update){ $sql="insertintotreevalues(null,'{$name}',$lft,$rgt,0);"; $sql1="updatetreesetrgt=rgt+2wherergt>={$row['lft']};"; $sql2="updatetreesetlft=lft+2wherelft>={$row['lft']};"; }else{ $sql="updatetreesetlft=$lft,rgt=$rgt,status=0wherename='{$name}';"; $sql1="updatetreesetrgt=rgt+2wherestatus=0andrgt>={$row['lft']};"; $sql2="updatetreesetlft=lft+2wherestatus=0andlft>={$row['lft']};"; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql);//lastaddnewdata } //无父无兄(大佬) if(!($pid||$proot)&&!($nid||$nroot)){ $sql="SELECTmax(`rgt`)asrgtFROMtree;"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); unset($sql); //新节点 $lft=1; $rgt=$row['rgt']+2; if(!$update){ $sql="insertintotreevalues(null,'{$name}',$lft,$rgt,0);"; $sql1="updatetreesetrgt=rgt+1"; $sql2="updatetreesetlft=lft+1"; }else{ $sql="updatetreesetlft=$lft,rgt=$rgt,status=0wherename='{$name}';"; $sql1="updatetreesetrgt=rgt+1wherestatus=0"; $sql2="updatetreesetlft=lft+1wherestatus=0"; } mysql_query($sql1); mysql_query($sql2); mysql_query($sql);//lastaddnewdata } } /** *用于删除一个节点(包括子节点) *@paramarray$data=array('id'=>主键,'root'=>名称)二选一 *@paramint$update默认为空,为1时逻辑删除 */ functiondelete_tree_all($data,$update=''){ $id=$data['id']?intval($data['id']):''; $root=$data['root']; if(!$id&&!$root)return; $sql=$id?"SELECTlft,rgtFROMtreeWHEREid='{$id}';":"SELECTlft,rgtFROMtreeWHEREname='{$root}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); unset($sql); $middle=$row['rgt']-$row['lft']+1; if(!$update){ $sql="deletefromtreewherelftBETWEEN'".$row['lft']."'AND'".$row['rgt']."'"; $sql1="updatetreesetrgt=rgt-{$middle}wherergt>{$row['rgt']}"; $sql2="updatetreesetlft=lft-{$middle}wherelft>{$row['rgt']}"; }else{ $sql="updatetreesetstatus=1wherelftBETWEEN'".$row['lft']."'AND'".$row['rgt']."'"; $sql1="updatetreesetrgt=rgt-{$middle}wherestatus=0andrgt>{$row['rgt']}"; $sql2="updatetreesetlft=lft-{$middle}wherestatus=0andlft>{$row['rgt']}"; } mysql_query($sql); mysql_query($sql1); mysql_query($sql2); } /** *用于删除一个节点(不包括子节点) *@paramarray$data=array('id'=>主键,'root'=>名称)二选一 *@paramint$update默认为空,为1时逻辑删除 */ functiondelete_tree_item($data,$update=''){ $id=$data['id']?intval($data['id']):''; $root=$data['root']; if(!$id&&!$root)return; $sql=$id?"SELECTid,lft,rgtFROMtreeWHEREid='{$id}';":"SELECTid,lft,rgtFROMtreeWHEREname='{$root}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); unset($sql); if(!$update){ $sql="deletefromtreewhereid={$row['id']};"; $sql1="updatetreesetrgt=rgt-1,lft=lft-1wherelft>{$row['lft']}andrgt<{$row['rgt']}"; $sql2="updatetreesetlft=lft-2wherelft>{$row['rgt']}"; $sql3="updatetreesetrgt=rgt-2wherergt>{$row['rgt']}"; }else{ $sql="updatetreesetstatus=1whereid={$row['id']};"; $sql1="updatetreesetrgt=rgt-1,lft=lft-1wherestatus=0andlft>{$row['lft']}andrgt<{$row['rgt']}"; $sql2="updatetreesetlft=lft-2wherestatus=0andlft>{$row['rgt']}"; $sql3="updatetreesetrgt=rgt-2wherestatus=0andrgt>{$row['rgt']}"; } mysql_query($sql); mysql_query($sql1); //candoornotdojustright,butnotdoloadempty2numberinmiddle mysql_query($sql2); mysql_query($sql3); } /** *用于获取所有的节点 *@paramarray$data=array('id'=>主键,'root'=>名称)二选一 */ functionget_tree_all($data){ $id=$data['id']?intval($data['id']):''; $root=$data['root']; if(!$id&&!$root)return; $sql=$id?"SELECTlft,rgtFROMtreeWHEREid='{$id}';":"SELECTlft,rgtFROMtreeWHEREname='{$root}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); $adata=array();//所有数据 $right=array();//计数 $prev=array(); $result=mysql_query("SELECTid,name,lft,rgtFROMtreeWHERElftBETWEEN'".$row['lft']."'AND'".$row['rgt']."'ORDERBYlftASC;"); 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; } /** *用于展示分类 *@paramarray$data=array('id'=>主键,'root'=>名称)二选一 */ functiondisplay_tree($data){ $id=$data['id']?intval($data['id']):''; $root=$data['root']; if(!$id&&!$root)return; $sql=$id?"SELECTlft,rgtFROMtreeWHEREid='{$id}';":"SELECTlft,rgtFROMtreeWHEREname='{$root}';"; $result=mysql_query($sql); $row=mysql_fetch_assoc($result); $right=array(); $result=mysql_query("SELECTname,lft,rgtFROMtreeWHERElftBETWEEN'".$row['lft']."'AND'".$row['rgt']."'ORDERBYlftASC;"); while($row=mysql_fetch_assoc($result)){ if(count($right)>0){//检查我们是否应该将节点移出堆栈 while($right[count($right)-1]<$row['rgt']){ array_pop($right); } } echostr_repeat('',count($right)).$row['name']."\n"; $right[]=$row['rgt']; } } mysql_connect('localhost','root','')ordie('connecterror'); mysql_select_db('test')ordie('databaseerror'); mysql_query('setnamesutf8'); 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程序设计有所帮助。