在国外网友的类上面加了中文注释,并添加了一个函数方便使用时调用,这个是基于左右值的无限分类,真正实现了无限分类,优点在于查询时速度快,缺点是添加分类时需要更新多个相关分类的左右值
完整代码下载 没有附使用方法了,表在分类的顶部有
http://www.dayanmei.com/download.php?filename=class.tree.rar
<?php
/*
Tree management class.
Written by Poetro ( poetro@c2design.hu )
Version 1.0 2005. 01. 04.
Modify by lee (psdshow@yahoo.com.cn) 2008-1-21
Adds, deletes, moves nodes, and retrieves tree in different methods
CREATE TABLE $table (
id int(10) unsigned NOT NULL auto_increment,
lft int(10) unsigned NOT NULL default '0',
rgt int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id),
KEY lft (lft),
KEY rgt (rgt)
) TYPE=MyISAM;
INSERT INTO $table VALUES (NULL, 0, 1);
*/
class Tree {
var $table;
function Tree($ttable) {
$this->table = $ttable;
}
// Retrieve the tree with the predefined parameters with the given root
// 根据给定的id显示分类树
/*
* $id 分类
* $indent 缩进符号
* $newLine 换行符号
* 更改其他的方式调用显示可以修改此或扩展此函数
*/
function retrieve($id, $indent='|-', $newLine="<br />") {
$output = '';
// retrieve the left and right value of the $root node
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
// start with an empty $right stack
$right = array();
// now, retrieve all descendants of the $root node
$query = 'SELECT id, lft, rgt FROM '.$this->table.
' WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC';
$result = mysql_query($query);
// display each row
while ($row = mysql_fetch_array($result)) {
// only check stack if there is one
if (count($right)>0) {
// check if we should remove a node from the stack
while ($right[count($right)-1]<$row['rgt']) {
array_pop($right);
}
}
// display indented node title
$output.=str_repeat($indent,count($right)).$row['id'].$newLine;
// add this node to the stack
$right[] = $row['rgt'];
}
}
return $output;
}
/* Retrieves the tree in an array.
Each depth's 0 index is the item and the others are the descendants of that item.
*/
/*
* 返回一个数组树
* 给定的分类的深度为 0
*/
function retrieve2array($id) {
$arr = array();
// retrieve the left and right value of the $root node
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
// start with an empty $right stack
$right = array();
// now, retrieve all descendants of the $root node
$query = 'SELECT * FROM '.$this->table.
' WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC';
$result = mysql_query($query);
// add each row to the array
while ($row = mysql_fetch_assoc($result)) {
// only check stack if there is one
if (count($right)>0) {
// check if we should remove a node from the stack
while ($right[count($right)-1]<$row['rgt']) {
array_pop($right);
}
}
// add the new element to the array
$this->_addToArray($arr, count($right), $row);
// add this node to the stack
$right[] = $row['rgt'];
}
return $arr[0];
}
return $arr;
}
/*
* 如果实用上面的函数仍然需要计算层数,或者也可以使用getDepths直接统计出层数,直接带入
* 返回一个没有带有深度数组树 这个函数把层数记录在deep里面了
*/
function sort2array($id) {
$arr = array();
// retrieve the left and right value of the $root node
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
// start with an empty $right stack
$right = array();
// now, retrieve all descendants of the $root node
$query = 'SELECT * FROM '.$this->table.
' WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC';
$result = mysql_query($query);
// add each row to the array
while ($row = mysql_fetch_assoc($result)) {
// only check stack if there is one
if (count($right)>0) {
// check if we should remove a node from the stack
while ($right[count($right)-1]<$row['rgt']) {
array_pop($right);
}
}
$arr[] = array('Sort'=>$row,'Deep'=>count($right));
// add this node to the stack
$right[] = $row['rgt'];
}
return $arr;
}
return $arr;
}
/*
Helper function
Creates a new item in a new element of the array at $depth depth, and sets it to $item
*/
function _addToArray(&$array, $depth, $item) {
// prepare a temporary pointer for the array walk
$arr=&$array;
// go threw the array and set pointer to the last element which is not an empty array
$i=0;
while($i<$depth && $c=count($arr)) {
$arr=&$arr[$c-1];
$i++;
}
// create a new array at the end
$arr[]=array();
// add a new element to that array
$arr[count($arr)-1][]=$item;
}
/* Retrieve the tree with the given root in an other method
Each depth's 0 index is the item and the others are the descendants of that item.
*/
function retrieve2array_ext($id) {
// retrieve the left and right value of the $root node
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
$arr = array();
if($row = mysql_fetch_assoc($result)) {
// start with an empty $right stack
$right = array();
// now, retrieve all descendants of the $root node
$result = mysql_query('SELECT * FROM '.$this->table.' WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC');
// add each row to the array
while ($row = mysql_fetch_assoc($result)) {
// only check stack if there is one
if (count($right)>0) {
// check if we should remove a node from the stack
while ($right[count($right)-1] < $row['rgt']) {
array_pop($right);
}
}
// add the new element to the array
$this->_addToArray($arr, count($right), $row);
// add this node to the stack
$right[] = $row['rgt'];
}
return $arr[0];
}
return $arr;
}
// Returns path to the element with the given id in an associated array (id => resultset)
/*
* 返回给定id的父类路径
*/
function pathTo($id) {
$results=array();
if($id) {
$query = 'SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id;
$result = mysql_query($query);
if($row = mysql_fetch_assoc($result)) {
$query = 'SELECT * FROM '.$this->table.' WHERE lft <= '.$row['lft'].
' AND rgt >= '.$row['rgt'].' ORDER BY lft ASC';
$result = mysql_query($query);
while( $row = mysql_fetch_assoc($result) ) {
$results[$row['id']] = $row;
}
}
}
return $results;
}
// Retrieves the number of descendants of the given id or -1 if not found or no params
/*
* 返回子分类的数量
*/
function descendants($id) {
$retVal=-1;
if($id) {
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
$retVal=($row['rgt']-$row['lft']-1)/2;
}
}
return $retVal;
}
// Retrieves the depth of each node starting with $root in an associated array (id => depth)
/*
* 返回所有id对应的深度(层)数组
*/
function getDepths() {
$results=array();
$query = 'SELECT T1.id, COUNT(T1.id) AS depth FROM '.$this->table.' AS T1, '.$this->table.
' AS T2 WHERE T1.lft BETWEEN T2.lft AND T2.rgt GROUP BY T1.id ORDER BY T1.lft';
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
$results[$row['id']] = $row['depth'];
}
return $results;
}
// Get elements on the selected depth in an associated array (id => resultset)
/*
* 返回给定深度的id 数组
*/
function getDepth($depth=1) {
$results=array();
$query = 'SELECT T1.*, T1.id, COUNT(T1.id) AS depth FROM '.
$this->table.' AS T1, '.$this->table.
' AS T2 WHERE T1.lft BETWEEN T2.lft AND T2.rgt GROUP BY T1.id HAVING depth='.$depth.
' ORDER BY T1.lft';
$result = mysql_query($query);
while ($row = mysql_fetch_assoc($result)) {
$results[$row['id']] = $row;
}
return $results;
}
// Get the direct descendant of an element with the given id in an associated array (id => resultset)
/*
* 返回给定id的直系子分类 数组
*/
function getDirectDescendants($id) {
$results=array();
// get the depth, and left right values of the selected element
$query = 'SELECT T1.id, T1.lft, T1.rgt, COUNT(T1.id) AS depth FROM '.$this->table.' AS T1, '.
$this->table.' AS T2 WHERE T1.lft BETWEEN T2.lft AND T2.rgt AND T1.id='.$id.
' GROUP BY T1.id ORDER BY T1.lft';
$result = mysql_query($query);
if($row = mysql_fetch_assoc($result)) {
// get the elements under the selected element
$query = 'SELECT T1.*, COUNT(T1.id) AS depth FROM '.
$this->table.' AS T1, '.$this->table.
' AS T2 WHERE T1.lft BETWEEN T2.lft AND T2.rgt AND T1.lft BETWEEN '.
$row['lft'].' AND '.$row['rgt'].' GROUP BY T1.id HAVING depth='.($row['depth']+1).
' ORDER BY T1.lft';
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
$results[$row['id']] = $row;
}
}
return $results;
}
// Add a node under the element with the given id.
// Returns the id of the new element or -1 if NO elements with the given id
/*
* 增加一个分类到指定id 返回一个插入后的id值
*/
function addNode($id) {
if($id) {
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
$result = mysql_query('UPDATE '.$this->table.' SET rgt=rgt+2 WHERE rgt>'.($row['rgt']-1));
$result = mysql_query('UPDATE '.$this->table.' SET lft=lft+2 WHERE lft>'.($row['rgt']-1));
$result = mysql_query('INSERT INTO '.$this->table.' (lft, rgt) VALUES('.$row['rgt'].', '.($row['rgt']+1).')');
return mysql_insert_id();
}
else {
return -1;
}
}
else {
return -1;
}
}
// Retrieves true if the Node with the given id is a leaf otherwise false
/*
* 检测给定id是否最底层分类 如果是返回ture
*/
function leaf($id) {
$query = 'SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id;
$result = mysql_query($query);
if($row = mysql_fetch_assoc($result)) {
if($row['lft']+1==$row['rgt']) {
return true;
}
}
return false;
}
// Delete the node with the given id and returns 1 if it is a node otherwise if found -1, if not in tree 0
/*
* 删除一个给定分类 只能删除没有子分类的分类 成功删除返回 1
*/
function delNode($id) {
if($id) {
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
//row found detects if it is a leaf
if($row['lft']+1==$row['rgt']) {
$result = mysql_query('UPDATE '.$this->table.' SET rgt=rgt-2 WHERE rgt>'.($row['rgt']-1));
$result = mysql_query('UPDATE '.$this->table.' SET lft=lft-2 WHERE lft>'.($row['rgt']-1));
$result = mysql_query('DELETE FROM '.$this->table.' WHERE id='.$id);
return 1;
}
else {
return -1;
}
}
}
//row not found or not leaf
return 0;
}
// Moves the node with the given id ($id) under the node whose id is $pid
/*
* 移动一个分类到指定的分类 只能移动一个没有子分类的分类到别的分类
*/
function moveNode($id, $pid) {
if($id && $pid) {
// get the node
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$id);
if($row = mysql_fetch_assoc($result)) {
// row found detects if it is a leaf
if($row['lft']+1==$row['rgt']) {
$orgt=$row['rgt'];
// get the parent
$result = mysql_query('SELECT lft, rgt FROM '.$this->table.' WHERE id='.$pid);
if($row = mysql_fetch_assoc($result)) {
// parent found, update nodes
$result = mysql_query('UPDATE '.$this->table.' SET rgt=rgt-2 WHERE rgt>'.($orgt-1));
$result = mysql_query('UPDATE '.$this->table.' SET lft=lft-2 WHERE lft>'.($orgt-1));
$result = mysql_query('UPDATE '.$this->table.' SET rgt=rgt+2 WHERE rgt>'.($row['rgt']-1));
$result = mysql_query('UPDATE '.$this->table.' SET lft=lft+2 WHERE lft>'.($row['rgt']-1));
$result = mysql_query('UPDATE '.$this->table.' SET lft='.$row['rgt'].', rgt='.($row['rgt']+1).' WHERE id='.$id);
return 1;
}
}
}
}
return 0;
}
}
?>
(140)
(125)
(198)
(80)
(70)
(23)
(6)
(108)
(27)
(24)
(15)
(6)
(2)
(2)
(11)
(3)