最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
php 树型结构操作类代码
时间:2022-06-24 18:32:50 编辑:袖梨 来源:一聚教程网
/***************************************************************
* 树型结构操作类(如果可以写成存储过程最理想)
*
* ***************************************************************/
class treenode {
var $f_id = 'id';
var $f_pid = 'pid';
var $f_lft = 'lft';
var $f_rgt = 'rgt';
var $f_s = 'sequence';
var $f_level = 'lev';
var $f_child_num = 'child_num';
var $table;
var $db;
/**
* 构造函数
* @param string $table 表名
* @param object $dbhanle adodb数据库教程操作句柄
*/
function treenode($table, $dbhandle) {
$this->db = $dbhandle;
$this->table = $table;
//$this->db->debug = true;
}
/**
* 增加子节点
* @param array $data 节点数据
* @return bool
*/
function addchild($data){
$pid = $data[$this->f_pid];
$sql = "select max({$this->f_s}) from {$this->table} where {$this->f_pid}=$pid";
$data[$this->f_s] = $this->db->getone($sql) + 1;//得到待插入节点的序号
$sql = "select * from {$this->table} where {$this->f_id} = -1";
$rs = $this->db->execute($sql);
$sql = $this->db->getinsertsql($rs, $data);
$this->db->execute($sql); //插入节点数据
if(!$this->db->affected_rows()){
return false;
}
$this->buildtree(1,1); //重建节点左右值
$this->updatelevel(1); //生成节点级数值
return true;
}
/**
* 修改节点的数据
* @param int $id 节点id号
* @param array $data 节点数据
* @return bool
*/
function updatenode($id, $data) {
//==>
unset($data[$this->f_id]);
unset($data[$this->f_pid]);
unset($data[$this->f_lft]);
unset($data[$this->f_rgt]);
unset($data[$this->f_s]);
unset($data[$this->f_level]);
//<==防止直接修改节点之间的关系,因为可能会导致节点关系混乱
$sql = "select * from ".$this->table." where {$this->f_id} = $id";
$rs = $this->db->execute($sql);
$sql = $this->db->getupdatesql($rs, $data);
if (!$this->db->execute($sql)) {
return false;
}
return true;
}
/**
* 删除节点
* @param int $id 节点id号
*/
function delnode($id) {
$childnode = $this->getchild($id);
$sql = "delete from {$this->table} where {$this->f_id} in($childnode)";
$rs = $this->db->execute($sql); //把指定节点和其下的子节点一并删除,
$this->buildtree(1,1);
}
/**
* 移动节点位置
* @param int $id 节点id号
* @param string 'up'|string 'down' 移动方向,'up'或'down'
* @param int $step 移动的步长
*/
function movenode($id,$direction,$step=1){
$sql = "select {$this->f_s},{$this->f_pid} from {$this->table} where {$this->f_id}=$id";
$row = $this->db->getrow($sql);
$pos = $row[$this->f_s]; //原次序
$pid = $row[$this->f_pid];
if('up' == $direction){
//计算新的次序值,(上移)
$pos_to = (($pos - $step)<1) ? 1 : $pos - $step;
}
else{
//计算新的次序值,(下移)
$sql = "select max({$this->f_s}) from {$this->table} where $this->f_pid = $pid";
$sequence_max = $this->db->getone($sql);
$pos_to = ($pos + $step)>$sequence_max ? $sequence_max : $pos + $step;
}
$sql = "update $this->table set $this->f_s = 0 where $this->f_id = $id";
$rs = $this->db->execute($sql);
$sql = "update {$this->table} set {$this->f_s} = $pos where {$this->f_pid} = $pid and {$this->f_s}=$pos_to";
$rs = $this->db->execute($sql);
$sql = "update {$this->table} set {$this->f_s}=$pos_to where {$this->f_id} = $id";
$rs = $this->db->execute($sql);
$this->buildtree(1,1);
}
/**
* 重建指定节点的子节点的lft,rgt值
* @param int $id 节点的id号
* @param int $left 节点left值
*/
function buildtree($id, $left) {
$right = $left +1;
$sql = "select $this->f_id from $this->table where $this->f_pid = $id order by $this->f_s asc";
$rs = $this->db->execute($sql);
while (!$rs->eof) {
$right = $this->buildtree($rs->fields[$this->f_id], $right);
$rs->movenext();
}
$sql = "update $this->table set $this->f_lft = $left, $this->f_rgt = $right, $this->f_child_num = ($this->f_rgt-$this->f_lft-1)/2 where $this->f_id = $id";
$this->db->execute($sql);
return $right +1;
}
/**
* 重新生成指定节点和其下的所有节点级数值
*/
function updatelevel($id){
$nodes = $this->getchild($id,false);
$nodes[] = $id;
foreach($nodes as $v){
$level = $this->getlevel($v);
$sql = "update $this->table set $this->f_level=$level where $this->f_id=$v";
$this->db->execute($sql);
}
}
/**
* 重新挂接节点
* @param int $id 节点id号
* @param int $to 要挂接到的节点id号
*/
function remountnode($id,$to){
$child = $this->getchild($id,false);
if(!$this->db->getone("select count(*) from {$this->table} where {$this->f_id}=$to")){
core::raisemsg("错误!将要挂接到的节点'$to'不存在!");
}
if(in_array($to,$child)){
core::raisemsg("错误!挂接到的节点'$to'是待挂接节点'$id'的一个子节点!");
}
$sql = "select max($this->f_s) from ".$this->table." where pid = $to";
$sequence = $this->db->getone($sql) + 1;
$sql = "update {$this->table} set {$this->f_pid} = $to, {$this->f_s}=$sequence where {$this->f_id}=$id";
$this->db->execute($sql);
$this->buildtree(1,1);
$this->updatelevel(1);
}
/**
* 得到指定节点的级数
* @param int $id 节点id号
*/
function getlevel($id){
$sql = "select count(*) from $this->table as c1,$this->table c2 where c1.$this->f_id = $id and c1.$this->f_lft between c2.$this->f_lft and c2.$this->f_rgt";
return $this->db->getone($sql);
}
/**
* 判断id号是否已存在
*/
function isexist($id, $me = null) {
$sql = "select ".$this->f_id." from ".$this->table." where ".$this->f_id."=$id";
$another = $this->db->getone($sql);
if (!strlen($another)) return false;
else if ($another == $me) return false;
else return true;
}
/**
* 得到指定节点的所有子节点
* @param int $id 节点id号
* @param string $mode 返回的数据类型
* 'str'为用','号连接的字串其它为数组
*/
function getchild($id,$strmode = true){
$sql = "select n1.$this->f_id as id from $this->table n1,$this->table n2 where n2.$this->f_id=$id and n1.$this->f_lft between n2.$this->f_lft and n2.$this->f_rgt";
$rs = $this->db->execute($sql);
while(!$rs->eof){
if($strmode)
$node .= $rs->fields[$this->f_id].',';
else $node[] = $rs->fields[$this->f_id];
$rs->movenext();
}
if($strmode){
$node = substr($node,0,-1);
if(strlen($node)){
return $node;
}
else return '0';
}
else return $node;
}
}
相关文章
- 王者荣耀侦探能力大测试攻略 王者荣耀侦探能力大测试怎么过 11-22
- 无期迷途主线前瞻兑换码是什么 11-22
- 原神欧洛伦怎么培养 11-22
- 炉石传说网易云音乐联动怎么玩 11-22
- 永劫无间手游确幸转盘怎么样 11-22
- 无期迷途主线前瞻兑换码是什么 无期迷途主线前瞻直播兑换码介绍 11-22