db = $db; $this->CategoryTable = "ar_category"; $this->fld_left = "lft"; $this->fld_right = "rgt"; $this->fld_tid = "tid"; $this->DeepTitle = "ROOTDEEP"; $this->DataNewsCode = "datanews"; } function GetFullCategory() { return $this->GetCategory(0,''); } /** * GetTree() 获得栏目树 * 用来获得某个栏目下或者所有栏目的树结构 * * 典型表结构 * (PostgreSql) * CREATE TABLE ar_category ( id serial NOT NULL, title character varying(80), tid integer NOT NULL DEFAULT 0, lft integer NOT NULL DEFAULT 0, rgt integer NOT NULL DEFAULT 0, CONSTRAINT ar_category_pkey PRIMARY KEY (id) ) * * @param int $tid * * @return array; */ function GetCategory($tid=0,$ptype='news'){ $left = $this->fld_left; $right = $this->fld_right; $categoryTable = $this->CategoryTable; $tidField = $this->fld_tid; $whereSql = array(); if(!empty($tid)) { $sql = "SELECT $left,$right FROM $categoryTable WHERE id=$tid"; $sth = $this->db->query($sql); $row = $sth->fetch(); $whereSql[] = " $left BETWEEN {$row[$left]} AND {$row[$right]} "; } if(count($whereSql)>0) { $whereSql = " WHERE ".join(" AND ",$whereSql); }elseif ($ptype<>''){ $whereSql = " where ptype='$ptype' "; } else $whereSql=''; $sql = "SELECT * FROM $categoryTable $whereSql ORDER BY ptype ASC,$left ASC "; $sth = $this->db->query($sql); $rows = $sth->fetchAll(); $stack = array(); $categorys = array(); foreach($rows as $k=>$v) { /* 如果它是一个顶级栏目,则为它重置深度 */ if(empty($v[$tidField])) { $stack = array(); }else{ if(count($stack) > 1) { /* 在这个循环中必须追溯直至与其平级的分类 while循环无法重写条件中已经改变的变量 第一次max(array_keys($stack))赋值为当前深度 循环中的第一个if里max(array_keys($stack))是重新统计,而非使用一定义的 因为第二次循环到此时可能max(array_keys($stack))已经发生改变 第三处max(array_keys($stack))表示第一个if中没有break掉的深度值,所以也不能使用赋过值的变量代替。 加入brake 可使程序追溯至平级栏目即进行下一步操作 必须是倒序循环,多个平级栏目时,如果是正序列循环会到第一个平级的栏目后停止循环 */ for($i=max(array_keys($stack));$i>=0;$i--) if($v[$right]>$stack[max(array_keys($stack))]) { if(count($stack)<1) { break; } if($v[$right]>$stack[max(array_keys($stack))]) { array_pop($stack); }else{ break; } }//end if }//end if } //放入输出数组 $rows[$k][$this->DeepTitle] = count($stack); //将此节点加入栈中 $stack[] = $v[$right]; }// end foreach return $rows; } /** * Insert() 插入一个栏目 * 返回数组 left=>左值 right=>右值 * * * @param int $tid * * @return array */ function Insert($tid){ $left = $this->fld_left; $right = $this->fld_right; $categoryTable = $this->CategoryTable; //分别处理有上级栏目和没上级栏目的 if(!empty($tid)) { $sql = "SELECT $right FROM $categoryTable WHERE id=$tid"; $sth = $this->db->query($sql); $row = $sth->fetch(); $right_start = $row[$right]-1; //更新所有右值 $sql = "UPDATE $categoryTable SET $right=$right+2 WHERE $right>$right_start"; $this->db->exec($sql); //更新所有左值 $sql = "UPDATE $categoryTable SET $left=$left+2 WHERE $left>$right_start"; $this->db->exec($sql); //返回应该插入的左右值 $lft = $right_start + 1; $rgt = $lft + 1; return array( 'left'=>$lft, 'right'=>$rgt ); }else{ //取最大的右值 $sql = "SELECT $right FROM $categoryTable WHERE tid=0 ORDER BY $left DESC LIMIT 1"; $sth = $this->db->query($sql); $row = $sth->fetch(); $right_start = $row[$right]-1; if($right_start<1) { return array( 'left'=>1, 'right'=>2 ); } $lft = $right_start + 2; $rgt = $lft + 1; return array( 'left'=>$lft, 'right'=>$rgt ); } }//Insert function GetSunCount($left,$right){ return ($right-$left-1)/2; } //获取一个栏目 function GetOne($tid){ $wheresql = ""; if(is_numeric($tid)) { $wheresql = "id=$tid"; }else{ $wheresql = "code='$tid'"; } $sql = "SELECT * FROM ".$this->CategoryTable." WHERE $wheresql"; $sth = $this->db->query($sql); return $sth->fetch(); }//GetOne //获得子栏目 function getSubNode($left,$right,$data = NULL) { if(empty($data)) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_left.">$left AND ".$this->fld_right."<$right ORDER BY ".$this->fld_left." ASC"; $rs = $this->db->query($sql); $SN = $rs->fetchAll(); }else{ $SN = array(); foreach($data as $k=>$v) { if($left < $v[$this->fld_left] && $v[$this->fld_right] < $right) $SN[] = $data[$k]; } } return $SN; } //获取子栏目中的最大右值 function getMaxSubRight($left,$right){ $sql = "SELECT max(".$this->fld_right.") as mx FROM ".$this->CategoryTable." WHERE ".$this->fld_left.">".$left." AND ".$this->fld_right."<".$right; $rs = $this->db->query($sql); $row = $rs->fetch(); return $row['mx']; } //获取平级栏目中的上一个栏目 function prevnode($tid,$left,$right) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_tid."=$tid AND ".$this->fld_left."<$left AND ".$this->fld_right."<$right ORDER BY ".$this->fld_left." DESC LIMIT 1 "; $rs = $this->db->query($sql); $row = $rs->fetch(); if(empty($row)) { return NULL; } return $row; } //获取平级栏目中的下一个栏目 function nextnode($tid,$left,$right) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_tid."=$tid AND ".$this->fld_left.">$left AND ".$this->fld_right.">$right ORDER BY ".$this->fld_left." ASC LIMIT 1 "; $rs = $this->db->query($sql); $row = $rs->fetch(); if(empty($row)) { return NULL; } return $row; } //移动栏目 function move($action,$id){ if($action == 'up') { return $this->moveup($id); } if($action == "down") { return $this->movedown($id); } } //栏目上移 function moveup($id){ $info = $this->GetOne($id); $tid = $info[$this->fld_tid]; $left = $info[$this->fld_left]; $right = $info[$this->fld_right]; $prev = $this->prevnode($tid,$left,$right); if($prev === NULL ) { return "此栏目已位于平级栏目的顶端"; } if(is_array($prev)) { $this_fd = $right-$left; $this_ft = $left - $prev[$this->fld_left]; $prve_fd = $prev[$this->fld_right] - $prev[$this->fld_left]; $new_right = $prev[$this->fld_left] + $this_fd; $new_left = $right - $prve_fd; $prev_ft = $new_left - $prev[$this->fld_left]; $exec = array( 'success' => array(), 'error' => array() ); $sql_1 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$prev[$this->fld_left].",".$this->fld_right."=".$new_right. " WHERE id=$id"; $sql_2 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$new_left.",".$this->fld_right."=".$right. " WHERE id=".$prev['id']; if($this->db->exec($sql_1)) { $exec['success'][] = $info['title']."[$id] :移动成功!"; }else{ $exec['error'][] = $info['title']."[$id] :移动失败! 请手动在数据库中修改,目标左右值 ".$prev[$this->fld_left].":".$new_right; } if($this->db->exec($sql_2)) { $exec['success'][] = $prev['title']."[".$prev['id']."] :移动成功!"; }else{ $exec['error'][] = $prev['title']."[".$prev['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$new_left.":".$right; } $thisnode = $this->getSubNode($left,$right); $prevnode = $this->getSubNode($prev[$this->fld_left],$prev[$this->fld_right]); /* $a = array(); echo $prev[$this->fld_left].':'.$prev[$this->fld_right]." - ".$left.":".$right; echo "
"; echo $prev[$this->fld_left].':'.$new_right." - ".$new_left.":".$right; echo "
"; */ if(!empty($thisnode)) { foreach($thisnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]-$this_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /* echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
"; */ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } if(!empty($prevnode)) { foreach($prevnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]+$prev_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /* echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
"; */ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $prev['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $prev['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } return $exec; } if(is_string($prev)) { return $prev; } }//栏目上移 //栏目下移 function movedown($id){ $info = $this->GetOne($id); $tid = $info[$this->fld_tid]; $left = $info[$this->fld_left]; $right = $info[$this->fld_right]; $next = $this->nextnode($tid,$left,$right); if($next === NULL ) { return "此栏目已位于平级栏目的末端"; } if(is_array($next)) { $this_fd = $right-$left; $next_fd = $next[$this->fld_right] - $next[$this->fld_left]; $new_right = $left + $next_fd; $new_left = $next[$this->fld_right] - $this_fd; $this_ft = $new_left - $left; $next_ft = $next[$this->fld_left] - $left; //echo $id."[".$left .":".$right ."]-".$next['id']."[".$next[$this->fld_left].":".$next[$this->fld_right] . "]
"; //echo $next['id']."[".$left .":".$new_right ."]-".$id."[".$new_left.":".$next[$this->fld_right]."]

"; $exec = array( 'success' => array(), 'error' => array() ); $sql_1 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$new_left.",".$this->fld_right."=".$next[$this->fld_right]. " WHERE id=$id"; $sql_2 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$left.",".$this->fld_right."=".$new_right. " WHERE id=".$next['id']; if($this->db->exec($sql_1)) { $exec['success'][] = $info['title']."[$id] :移动成功!"; }else{ $exec['error'][] = $info['title']."[$id] :移动失败! 请手动在数据库中修改,目标左右值 ".$new_left.":".$next[$this->fld_right]; } if($this->db->exec($sql_2)) { $exec['success'][] = $next['title']."[".$next['id']."] :移动成功!"; }else{ $exec['error'][] = $next['title']."[".$next['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$left.":".$this->fld_right; } $thisnode = $this->getSubNode($left,$right); $nextnode = $this->getSubNode($next[$this->fld_left],$next[$this->fld_right]); if(!empty($thisnode)) { foreach($thisnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]+$this_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /*echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
";*/ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } if(!empty($nextnode)) { foreach($nextnode as $k=>$v) { $node_new_left = ($v[$this->fld_left] - $next_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /*echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
";*/ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } return $exec; } if(is_string($next)) { return $next; } }//栏目下移 }