写了一个PHP生成树的小例子,仅供大家参考.

时间:2021-03-19 12:38:48
只是起到一个抛砖引玉的作用.不要朝我身上扔砖家.以帮帮新手.

CREATE TABLE `tree` (
  `id` int(11) NOT NULL,
  `name` varchar(255) collate utf8_bin NOT NULL,
  `parent` int(11) NOT NULL,
  `ischild` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


<?php
header("content-type: text/html; charset=utf-8");
$connect = mysql_connect('localhost', 'root', '123456');
mysql_select_db("wz");
mysql_query("set names 'utf8'");
//获得顶节点
$sql = "select id, name,ischild from tree where parent = 0 order by id asc";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
extract($row);
        //如果有子节点,就在前面加个事件,以便展开或者关闭子节点
$icon = $ischild ? "<a href='javascript:expand(\"div$id\");'>+</a>":"-";
$name = $icon . $name;
echo "<div id='div" . $id . "'>" . $name;
if($ischild)
{
                //递归获取节点
getNode($id, 0);
}
echo "</div>";
}

function getNode($id, $level)
{
$sql = "select id, name, ischild from tree where parent = $id order by id asc ";
$result = mysql_query($sql);
$level++;
  while($row = mysql_fetch_array($result))
  {
   extract($row);
$icon = $ischild ? "<a href='javascript:expand(\"div$id\");'>+</a>":"-";
$name = $icon . $name;  
echo "<div id='div" . $id . "'>" . echoChar("&nbsp;&nbsp;&nbsp;&nbsp;", $level)  . $name;
if($ischild)
{
getNode($id, $level);
}
echo "</div>";
  }
}

function echoChar($char, $num)
{
for($i=0;$i< $num; $i++)
{
$strChar .= $char;
}
return $strChar;
}
?>
<script language="javascript">
function expand(id)
{
var obj = document.getElementById(id).childNodes;
for(var i=0;i<obj.length;i++)
{
if(obj[i].nodeName == "DIV")
{
switch(obj[i].style.display)
{
case "":
case "block":
 obj[i].style.display = "none";
 break;
case "none":
 obj[i].style.display = "block";
 break; 
}
}
}
}
</script>

55 个解决方案

#1


哈,不错!

#2


谢谢提供!

#3


不错

#4


学习收藏!

#5


你的js部分不是很明白,我刚才找了一个js帮助文档,怎么没有找到getElementById(id),childNodes等等一些的东西呢?
能否给我细致讲一下呢 具体的含义。如果按照你说的那样的话,如何去美化?

#6


getElementById获取节点为xx的html对象.
childNodes这是一个html对象子点列表.

这是dom的节点思想,呵呵.详细的可以看手册.
http://www.xulplanet.com/references/objref/HTMLTableRowElement.html

#7


美化无非是加些图片呀,然后再给节点加链接呀什么的.
还有加上小横小竖杠,加上节点展开和收缩图标的变化等等.

#8


顶一下。

#9


收藏 ,感谢楼主~!

#10


代码很漂亮~

#11


学习

#12


谢了

#13


去看
我发现自己做一个东西这么难得原因在哪里了
不懂得东西太多了!
楼主  可要多多指教阿!

#14


$icon = $ischild ? "<a href='javascript:expand(\"div$id\");'>+</a>":"-";
这句话中的$id怎么传值呢?
我的那条语句是这样的select upcode,upname,dcode,dname,ditem,producdwgcode from table where upcode = productdwg;
我是把upcode传递进取 我想利用$row[“upcode”] 该如何实现呢  总是实现不了
等待指教。

#15


引用 14 楼 cyxin2121921 的回复:
$icon = $ischild ? " <a href='javascript:expand(\"div$id\");'>+ </a>":"-"; 
这句话中的$id怎么传值呢? 
我的那条语句是这样的select upcode,upname,dcode,dname,ditem,producdwgcode from table where upcode = productdwg; 
我是把upcode传递进取 我想利用$row[“upcode”] 该如何实现呢  总是实现不了 
等待指教。

mysql_fecth_array返回以字段为索引的数组.
extract($row)生成以索引为变量名,以其对应值为值的为变量.
所以$id其实就是字段的值.

#16


我刚才尝试了一下  <a href='javascript:expand(\"div$id\");'>+ </a>":"-"; 这句话好像执行不到
是不是我应该点击加号或是减号的时候就应该能够实现它的子节点的吧
但是我一旦点击加号或是减号的时候  就提示我 第一行缺少对象
一下是我按照你给我提供的代码我做了简单修改后形成的 
可以取到第一组根节点  就没有子节点了
如何才能够判断执行了 这个js脚本语言呢
如可以帮我看看吧
我的邮箱是cuiyaxin@tangche.com 如果可以 您可以往这个邮箱中联系我!
<?php
    include 'include/pdmdblogon.php';

if(!$conn){
echo "注意:当前无法连接PDM数据库。";//连接错误提示
exit;}
//获得顶节点
$mysql = "SELECT DISTINCT UPCODE,PRODUCTDWGCODE,UPNAME FROM XTDETAMSALL_DETAIL";
$mysql .= " WHERE UPCODE = PRODUCTDWGCODE";
$stmt = ociparse($conn,$mysql);
if(!$stmt)
{
echo "ERROR - Could not parse SQL statement.";
exit;
}
ociexecute($stmt);
while(ocifetchinto($stmt,$row,OCI_ASSOC)){
    extract($row);
//echo "$UPNAME";
$mysql1 = "SELECT count(*) AS t FROM XTDETAMSALL_DETAIL WHERE upcode = '$UPCODE'";
$stmt1 = ociparse($conn,$mysql1);
$exi = ociexecute($stmt1);
    


$icon = $exi?"<a href='javascript:expand(\"div$UPCODE\");'>+</a>":"-";
$UPNAME = $icon.$UPNAME;
echo "<div upcode='div".$UPCODE."'>".$UPNAME;
if($exi)
{
  
        getNode($UPCODE,$PRODUCTDWGCODE,1);   
}

}

function getNode($upcode,$productdwgcode,$node_level)
{
        include 'include/pdmdblogon.php';
   $sql = "SELECT DISTINCT UPCODE,UPNAME,DITEM,DCODE,DNAME,PRODUCTDWGCODE  FROM XTDETAMSALL_DETAIL";
$sql .= " WHERE UPCODE = '{$UPCODE}' AND PRODUCTDWGCODE = '{$PRODUCTDWGCODE}'";
$sql .= " ORDER BY DITEM";

$stmt = ociparse($conn,$sql);
if(!$stmt)
{
echo "ERROR - Could not parse SQL statement.";
exit;
}
ociexecute($stmt);


$node_level++;

while(ocifetchinto($stmt,$rows,OCI_ASSOC))
{
extract($row);
echo "$UPCODE";
echo "$UPNAME";
echo "$DCODE";echo "$DNAME";
echo "$DITEM";echo "$PRODUCTDWGCODE";

$mysql1 = "SELECT count(*) FROM XTDETAMSALL_DETAIL upcode = '{$upcode}'";
$stmt1 = ociparse($conn,$mysql1);

$exi =  ociexecute($stmt1);
$icon = $exi ? "<a href='javascript:expand(\"div$UPCODE\");'>+</a>":"-";
$UPNAME = $icon.$UPNAME;
echo "<div upcode='div".$UPCODE."'>".echoChar("&nbsp;&nbsp;&nbsp;&nbsp;",$node_level).$UPNAME;
if($exi)
{
    //echo "  ".$row['UPCODE']."$b";
    getNode($UPCODE,$PRODUCTDWGCODE,$node_level);   
}
echo "</div>";
}
}

function echoChar($char,$num)
{
for($i = 0;$i<$num;$I++)
{
$strChar .= $char;
}
return $strChar;
}


?>

<script language="javascript">
    function expand(upcode)
{
    
    var obj = document.getElementById(upcode).childNodes;
//alert(obj);
for(var i=0;i<obj.length;j++)
{
    if(obj[i].nodeName=="DIV")
{
    switch(obj[i].style.display)
{
    case "":
case "block":
    obj[i].style.display = "none";
break;
case "none";
    obj[i].style.display = "block";
break;
}
}
}
}
</script>

#17


感谢LZ,学习中。

#18


确实不错.

#19


学习

#20


学习一下

#21


mark

#22


*火最近挺火,支持ing!

#23


学习

#24


学习

#25


数据库输入中文显示乱码,不知咋回事,请赐教!

#26


顶一下,改改看看

#27


mark,有空学习,谢谢分享。

#28


楼主现在php版排名第一,不错!

#29


收藏!

#30


学习

#31


收藏

#32


提几个小小的改进建议:
1.把递归查询数据库改为一次性查询所有数据再用程序来递归处理,(尽可能少地查询数据库,这点很重要)
2.递归处理可以考虑搬到客户端,减轻服务器压力
3.可以考虑再添加一个冗余字段routing,把节点路径记录下来,也很有用,比如需要找出某个节点下的所有字节点,就不需要递归操作了(也许算个小技巧吧).
4.ischild也许可以换成一个子统计节点数的字段childnum,当childnum为0是表示它是字节点(childnum有时也挺有用的)

CREATE TABLE `tree` (
  `id` int(11) NOT NULL,
  `name` varchar(255) collate utf8_bin NOT NULL,
  `parent` int(11) NOT NULL,
  `childnum` int(11) NOT NULL default '0',  `routing` varchar(255),  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

#33


楼上的至少说明你是用心的来看这个程序了.
第一, 一次性全部读取来,再做递归处理.将数据库的查询转为服务器内存操作.这个可能要权衡一下利弊.
第二, 同意.但要研究一下,如何做.
第三, 这样写不是很灵活.我记得csdn上有一个帖子专门讨论过这个问题.
第四, 字段由可能的boolean变成int,怎么说呢.各有利弊吧.就是每加一个节点,你都要更新其父节点的这个字段的值.

这个小例子,主要是为了给新手提供一个参考,问题肯定是会有的,欢迎大家指正,呵呵.
共同讨论吗!

#34


感谢LZ分享,新手学习中

#35


新手学习

#36


谢谢分享 jf

#37


一个目录树就这么简单
我自己没写过
lz是无限级的吗

#38


提几个小小的改进建议: 
1.把递归查询数据库改为一次性查询所有数据再用程序来递归处理,(尽可能少地查询数据库,这点很重要) 
2.递归处理可以考虑搬到客户端,减轻服务器压力 
3.可以考虑再添加一个冗余字段routing,把节点路径记录下来,也很有用,比如需要找出某个节点下的所有字节点,就不需要递归操作了(也许算个小技巧吧). 
4.ischild也许可以换成一个子统计节点数的字段childnum,当childnum为0是表示它是字节点(childnum有时也挺有用的) 


-------------------------------------


最近看了一下
1\最近在测试,是一次查询好还是用时查询好,一次查询,则用数组解决;如果多次查询,递归时会不会出错?--我查询时好象老出问题,那个extract就有问题,楼主可以加点测试数据试试

2\树是一次生成还是Ajax生成,我觉和楼主可以先生成一个一次的,即一次先生成所有节点,先成功展开树!其他的再改进!
一次递归生成树,不知楼主的能不能行? 
   我测试比起来错不太容易!

3ischild也许可以换成一个子统计节点数的字段childnum? 可以的,如果查询检查,如果数组递归,算法会有稍差别


我的疑问,楼主在做查询递归时有没有成功?比如$conn,是否要成全局变量?如果能递归成功,这就容易多了?

#39


还没结啊,接着顶.

#40


#41


测试递归绝对是没有问题的,呵呵.
这是最基本的.

#42


呵呵,要是给一段测试数据就好了

#43


引用 33 楼 jakey9826 的回复:
楼上的至少说明你是用心的来看这个程序了. 
第一, 一次性全部读取来,再做递归处理.将数据库的查询转为服务器内存操作.这个可能要权衡一下利弊. 
第二, 同意.但要研究一下,如何做. 
第三, 这样写不是很灵活.我记得csdn上有一个帖子专门讨论过这个问题. 
第四, 字段由可能的boolean变成int,怎么说呢.各有利弊吧.就是每加一个节点,你都要更新其父节点的这个字段的值. 

这个小例子,主要是为了给新手提供一个参…

总的来讲,在我所遇到的大多数树结构应用中,一般还是查询为主,而且树的节点也不至少太多,节点数在1000以上的分类我估计实际应用中都比较少;
所以第三点,对我而言,我愿意牺点时间处理在维护树结构(主要是节点迁移)时带来的更新节点路径变化,其实也并不复杂.
当然对第四点,有另一个问题,如果一个父节点下面删除子节点的时候,需要重新判断ischild,这个和每次添加时更新数据
库处理都差不多.所以像你说的,各有利弊吧;
第二点,这个实现起来不难(我不打算给出示例代码,呵呵,因为我很懒^_^)
其实有人对第三点用字符串来作like查找存在效率的问题(我现在的项目组长就这么认为),其实不然,我测试过在一张百万级数据的表中用like '60000%'这样的查询用时一般在0.003S左右,而且这个字段没有加索引,所以我觉得这个根本不是问题.需要这种应用的情况主要是在有和情况需要把某节点下所有内容找出来的时候,如果没有这个routing,可能实现起来就麻烦了.
对第一点,我的看法是,一般来说,其实不管节点数多少,最终要用数据库服务器到应用服务器的数据都是一样的(严格的地说,递归查询数据库带来的网络流量和系统开销都要大).
我的语言表达能力实在太差,还请看的人请多多包涵

#44


但是现在我的展开和收缩功能还没有实现!
既然你测试成功了 怎么我就不能实现呢!

#45


新手
JF

#46


谢谢
学习中。

#47


测试了一下,可以显示


http://www.zzxj.net/web/memb_tree.php


测试数据

INSERT INTO `tree` (`id`, `name`, `parent`, `ischild`) VALUES 
(1, '中国', 0, 1),
(2, '美国', 0, 0),
(3, '日本', 0, 1),
(4, '浙江', 1, 1),
(5, '福建', 1, 0),
(6, '东京', 3, 0),
(7, '杭州', 4, 1),
(8, '温州', 4, 1),
(9, '鹿城', 8, 1),
(10, '鹿县', 9, 0),
(11, '鹿州', 7, 0);

#48


经修改实现CSDN树

花了一些时间,研究三种方式生成树:js树组,ajax 生成和PHP生成

比较而言ajax的相对好一些,因为只有点击时才查询,降低了不必要的查询
从数据库将数据提进数组生成只用一次查询,但算法稍多;
用数据库递归查询代码最少,但每次查询稍多;

以下是根据*火提供的代码修改而生的树,增加了一些算法:
里面应用了CSDN的CSS控制模式,图标里面均有,结构模式简单!适合研究

下面是效果:
http://www.zzxj.net/web/memb_tree_2.php

#49


学习下~~~

#50


学习下~~~

#1


哈,不错!

#2


谢谢提供!

#3


不错

#4


学习收藏!

#5


你的js部分不是很明白,我刚才找了一个js帮助文档,怎么没有找到getElementById(id),childNodes等等一些的东西呢?
能否给我细致讲一下呢 具体的含义。如果按照你说的那样的话,如何去美化?

#6


getElementById获取节点为xx的html对象.
childNodes这是一个html对象子点列表.

这是dom的节点思想,呵呵.详细的可以看手册.
http://www.xulplanet.com/references/objref/HTMLTableRowElement.html

#7


美化无非是加些图片呀,然后再给节点加链接呀什么的.
还有加上小横小竖杠,加上节点展开和收缩图标的变化等等.

#8


顶一下。

#9


收藏 ,感谢楼主~!

#10


代码很漂亮~

#11


学习

#12


谢了

#13


去看
我发现自己做一个东西这么难得原因在哪里了
不懂得东西太多了!
楼主  可要多多指教阿!

#14


$icon = $ischild ? "<a href='javascript:expand(\"div$id\");'>+</a>":"-";
这句话中的$id怎么传值呢?
我的那条语句是这样的select upcode,upname,dcode,dname,ditem,producdwgcode from table where upcode = productdwg;
我是把upcode传递进取 我想利用$row[“upcode”] 该如何实现呢  总是实现不了
等待指教。

#15


引用 14 楼 cyxin2121921 的回复:
$icon = $ischild ? " <a href='javascript:expand(\"div$id\");'>+ </a>":"-"; 
这句话中的$id怎么传值呢? 
我的那条语句是这样的select upcode,upname,dcode,dname,ditem,producdwgcode from table where upcode = productdwg; 
我是把upcode传递进取 我想利用$row[“upcode”] 该如何实现呢  总是实现不了 
等待指教。

mysql_fecth_array返回以字段为索引的数组.
extract($row)生成以索引为变量名,以其对应值为值的为变量.
所以$id其实就是字段的值.

#16


我刚才尝试了一下  <a href='javascript:expand(\"div$id\");'>+ </a>":"-"; 这句话好像执行不到
是不是我应该点击加号或是减号的时候就应该能够实现它的子节点的吧
但是我一旦点击加号或是减号的时候  就提示我 第一行缺少对象
一下是我按照你给我提供的代码我做了简单修改后形成的 
可以取到第一组根节点  就没有子节点了
如何才能够判断执行了 这个js脚本语言呢
如可以帮我看看吧
我的邮箱是cuiyaxin@tangche.com 如果可以 您可以往这个邮箱中联系我!
<?php
    include 'include/pdmdblogon.php';

if(!$conn){
echo "注意:当前无法连接PDM数据库。";//连接错误提示
exit;}
//获得顶节点
$mysql = "SELECT DISTINCT UPCODE,PRODUCTDWGCODE,UPNAME FROM XTDETAMSALL_DETAIL";
$mysql .= " WHERE UPCODE = PRODUCTDWGCODE";
$stmt = ociparse($conn,$mysql);
if(!$stmt)
{
echo "ERROR - Could not parse SQL statement.";
exit;
}
ociexecute($stmt);
while(ocifetchinto($stmt,$row,OCI_ASSOC)){
    extract($row);
//echo "$UPNAME";
$mysql1 = "SELECT count(*) AS t FROM XTDETAMSALL_DETAIL WHERE upcode = '$UPCODE'";
$stmt1 = ociparse($conn,$mysql1);
$exi = ociexecute($stmt1);
    


$icon = $exi?"<a href='javascript:expand(\"div$UPCODE\");'>+</a>":"-";
$UPNAME = $icon.$UPNAME;
echo "<div upcode='div".$UPCODE."'>".$UPNAME;
if($exi)
{
  
        getNode($UPCODE,$PRODUCTDWGCODE,1);   
}

}

function getNode($upcode,$productdwgcode,$node_level)
{
        include 'include/pdmdblogon.php';
   $sql = "SELECT DISTINCT UPCODE,UPNAME,DITEM,DCODE,DNAME,PRODUCTDWGCODE  FROM XTDETAMSALL_DETAIL";
$sql .= " WHERE UPCODE = '{$UPCODE}' AND PRODUCTDWGCODE = '{$PRODUCTDWGCODE}'";
$sql .= " ORDER BY DITEM";

$stmt = ociparse($conn,$sql);
if(!$stmt)
{
echo "ERROR - Could not parse SQL statement.";
exit;
}
ociexecute($stmt);


$node_level++;

while(ocifetchinto($stmt,$rows,OCI_ASSOC))
{
extract($row);
echo "$UPCODE";
echo "$UPNAME";
echo "$DCODE";echo "$DNAME";
echo "$DITEM";echo "$PRODUCTDWGCODE";

$mysql1 = "SELECT count(*) FROM XTDETAMSALL_DETAIL upcode = '{$upcode}'";
$stmt1 = ociparse($conn,$mysql1);

$exi =  ociexecute($stmt1);
$icon = $exi ? "<a href='javascript:expand(\"div$UPCODE\");'>+</a>":"-";
$UPNAME = $icon.$UPNAME;
echo "<div upcode='div".$UPCODE."'>".echoChar("&nbsp;&nbsp;&nbsp;&nbsp;",$node_level).$UPNAME;
if($exi)
{
    //echo "  ".$row['UPCODE']."$b";
    getNode($UPCODE,$PRODUCTDWGCODE,$node_level);   
}
echo "</div>";
}
}

function echoChar($char,$num)
{
for($i = 0;$i<$num;$I++)
{
$strChar .= $char;
}
return $strChar;
}


?>

<script language="javascript">
    function expand(upcode)
{
    
    var obj = document.getElementById(upcode).childNodes;
//alert(obj);
for(var i=0;i<obj.length;j++)
{
    if(obj[i].nodeName=="DIV")
{
    switch(obj[i].style.display)
{
    case "":
case "block":
    obj[i].style.display = "none";
break;
case "none";
    obj[i].style.display = "block";
break;
}
}
}
}
</script>

#17


感谢LZ,学习中。

#18


确实不错.

#19


学习

#20


学习一下

#21


mark

#22


*火最近挺火,支持ing!

#23


学习

#24


学习

#25


数据库输入中文显示乱码,不知咋回事,请赐教!

#26


顶一下,改改看看

#27


mark,有空学习,谢谢分享。

#28


楼主现在php版排名第一,不错!

#29


收藏!

#30


学习

#31


收藏

#32


提几个小小的改进建议:
1.把递归查询数据库改为一次性查询所有数据再用程序来递归处理,(尽可能少地查询数据库,这点很重要)
2.递归处理可以考虑搬到客户端,减轻服务器压力
3.可以考虑再添加一个冗余字段routing,把节点路径记录下来,也很有用,比如需要找出某个节点下的所有字节点,就不需要递归操作了(也许算个小技巧吧).
4.ischild也许可以换成一个子统计节点数的字段childnum,当childnum为0是表示它是字节点(childnum有时也挺有用的)

CREATE TABLE `tree` (
  `id` int(11) NOT NULL,
  `name` varchar(255) collate utf8_bin NOT NULL,
  `parent` int(11) NOT NULL,
  `childnum` int(11) NOT NULL default '0',  `routing` varchar(255),  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

#33


楼上的至少说明你是用心的来看这个程序了.
第一, 一次性全部读取来,再做递归处理.将数据库的查询转为服务器内存操作.这个可能要权衡一下利弊.
第二, 同意.但要研究一下,如何做.
第三, 这样写不是很灵活.我记得csdn上有一个帖子专门讨论过这个问题.
第四, 字段由可能的boolean变成int,怎么说呢.各有利弊吧.就是每加一个节点,你都要更新其父节点的这个字段的值.

这个小例子,主要是为了给新手提供一个参考,问题肯定是会有的,欢迎大家指正,呵呵.
共同讨论吗!

#34


感谢LZ分享,新手学习中

#35


新手学习

#36


谢谢分享 jf

#37


一个目录树就这么简单
我自己没写过
lz是无限级的吗

#38


提几个小小的改进建议: 
1.把递归查询数据库改为一次性查询所有数据再用程序来递归处理,(尽可能少地查询数据库,这点很重要) 
2.递归处理可以考虑搬到客户端,减轻服务器压力 
3.可以考虑再添加一个冗余字段routing,把节点路径记录下来,也很有用,比如需要找出某个节点下的所有字节点,就不需要递归操作了(也许算个小技巧吧). 
4.ischild也许可以换成一个子统计节点数的字段childnum,当childnum为0是表示它是字节点(childnum有时也挺有用的) 


-------------------------------------


最近看了一下
1\最近在测试,是一次查询好还是用时查询好,一次查询,则用数组解决;如果多次查询,递归时会不会出错?--我查询时好象老出问题,那个extract就有问题,楼主可以加点测试数据试试

2\树是一次生成还是Ajax生成,我觉和楼主可以先生成一个一次的,即一次先生成所有节点,先成功展开树!其他的再改进!
一次递归生成树,不知楼主的能不能行? 
   我测试比起来错不太容易!

3ischild也许可以换成一个子统计节点数的字段childnum? 可以的,如果查询检查,如果数组递归,算法会有稍差别


我的疑问,楼主在做查询递归时有没有成功?比如$conn,是否要成全局变量?如果能递归成功,这就容易多了?

#39


还没结啊,接着顶.

#40


#41


测试递归绝对是没有问题的,呵呵.
这是最基本的.

#42


呵呵,要是给一段测试数据就好了

#43


引用 33 楼 jakey9826 的回复:
楼上的至少说明你是用心的来看这个程序了. 
第一, 一次性全部读取来,再做递归处理.将数据库的查询转为服务器内存操作.这个可能要权衡一下利弊. 
第二, 同意.但要研究一下,如何做. 
第三, 这样写不是很灵活.我记得csdn上有一个帖子专门讨论过这个问题. 
第四, 字段由可能的boolean变成int,怎么说呢.各有利弊吧.就是每加一个节点,你都要更新其父节点的这个字段的值. 

这个小例子,主要是为了给新手提供一个参…

总的来讲,在我所遇到的大多数树结构应用中,一般还是查询为主,而且树的节点也不至少太多,节点数在1000以上的分类我估计实际应用中都比较少;
所以第三点,对我而言,我愿意牺点时间处理在维护树结构(主要是节点迁移)时带来的更新节点路径变化,其实也并不复杂.
当然对第四点,有另一个问题,如果一个父节点下面删除子节点的时候,需要重新判断ischild,这个和每次添加时更新数据
库处理都差不多.所以像你说的,各有利弊吧;
第二点,这个实现起来不难(我不打算给出示例代码,呵呵,因为我很懒^_^)
其实有人对第三点用字符串来作like查找存在效率的问题(我现在的项目组长就这么认为),其实不然,我测试过在一张百万级数据的表中用like '60000%'这样的查询用时一般在0.003S左右,而且这个字段没有加索引,所以我觉得这个根本不是问题.需要这种应用的情况主要是在有和情况需要把某节点下所有内容找出来的时候,如果没有这个routing,可能实现起来就麻烦了.
对第一点,我的看法是,一般来说,其实不管节点数多少,最终要用数据库服务器到应用服务器的数据都是一样的(严格的地说,递归查询数据库带来的网络流量和系统开销都要大).
我的语言表达能力实在太差,还请看的人请多多包涵

#44


但是现在我的展开和收缩功能还没有实现!
既然你测试成功了 怎么我就不能实现呢!

#45


新手
JF

#46


谢谢
学习中。

#47


测试了一下,可以显示


http://www.zzxj.net/web/memb_tree.php


测试数据

INSERT INTO `tree` (`id`, `name`, `parent`, `ischild`) VALUES 
(1, '中国', 0, 1),
(2, '美国', 0, 0),
(3, '日本', 0, 1),
(4, '浙江', 1, 1),
(5, '福建', 1, 0),
(6, '东京', 3, 0),
(7, '杭州', 4, 1),
(8, '温州', 4, 1),
(9, '鹿城', 8, 1),
(10, '鹿县', 9, 0),
(11, '鹿州', 7, 0);

#48


经修改实现CSDN树

花了一些时间,研究三种方式生成树:js树组,ajax 生成和PHP生成

比较而言ajax的相对好一些,因为只有点击时才查询,降低了不必要的查询
从数据库将数据提进数组生成只用一次查询,但算法稍多;
用数据库递归查询代码最少,但每次查询稍多;

以下是根据*火提供的代码修改而生的树,增加了一些算法:
里面应用了CSDN的CSS控制模式,图标里面均有,结构模式简单!适合研究

下面是效果:
http://www.zzxj.net/web/memb_tree_2.php

#49


学习下~~~

#50


学习下~~~