255 lines
5.6 KiB
PHP
255 lines
5.6 KiB
PHP
<?php
|
||
/**
|
||
* ArchiveCategroy - 文档分类类
|
||
*/
|
||
|
||
class ArchiveCategory
|
||
{
|
||
//PDO对象
|
||
private $db;
|
||
|
||
//数据库中分类表
|
||
public $CategoryTable;
|
||
|
||
//分类左值字段名称
|
||
private $fld_left;
|
||
|
||
//分类右值字段名称
|
||
private $fld_right;
|
||
|
||
//顶级栏目标记字段
|
||
private $fld_tid;
|
||
|
||
//输出栏目中的深度信息
|
||
public $DeepTitle;
|
||
|
||
//数据新闻栏目标识
|
||
public $DataNewsCode;
|
||
|
||
function __construct($db){
|
||
$this->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 GetRouter($lft,$rgt){
|
||
$sql = "SELECT * FROM ".$this->CategoryTable."
|
||
WHERE ".$this->fld_left." < $lft AND ".$this->fld_right." > $rgt
|
||
ORDER BY ".$this->fld_left." ASC;";
|
||
$sth = $this->db->query($sql);
|
||
$rows = $sth->fetchAll();
|
||
return $rows;
|
||
}
|
||
|
||
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
|
||
|
||
} |