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程序设计有所帮助。