本文实例讲述了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"] . "
";
$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程序设计有所帮助。