先说一点[要求树形的每一个节点都能展开和收拢并互不影响。]这个有点困难   用session来记录目前处于打开状态的结点列表吧讨论一哈

解决方案 »

  1.   


    建议使用
    http://www.posi.de的class.tree比你做的好的多,而且要比csdn的好看,呵呵
      

  2.   

    http://www.posi.de的class.tree也用到了js
    其实如果用js的话是很容易实现的,只要控制一下表格的显隐即可,这里要求用php来实现是为了彻底的隐藏不想显示东西,我已解决了在二维上的树形展开,不过用的办法不是递归,用递归的实现可能有点难,因为没有明确的父子关系在里面,而且这是维数上的深入,并不是可以无限分下去的,bluemeteor(挂月||╭∩╮(︶_︶)╭∩╮)提出的用session来存放节点列表的办法还没有试过,可以一试。
    请教一下唠叨,如果要实现的话还需要哪些条件?你所说的指示分支的方案是否是指标识该节点的方案呢?
    我现在是用get两个参数的办法来解决的,一个是action它的open和close用来打开和关闭树,另一个是expand它的值用来指向所开节点,不知道还有无更好的办法。
    其实要实现这个问题的主要目的是要解决在服务器端实现权限树,即有相应的权限才能看到相应的树,我很笨,还请大家指点。
      

  3.   

    <?php 
    $item1 = array( array('name' => 'A', 'url' => 'action.php?action=a'),array('name' => 'B', 'url' => 'action.php?action=b'));
    $item2 = array( array('name' => 'C', 'url' => 'action.php?action=c'),array('name' => 'D', 'url' => 'action.php?action=d'));
    $item3 = array( array('name' => 'E', 'url' => 'action.php?action=e'),array('name' => 'F', 'url' => 'action.php?action=r'));
    $item4 = array( array('name' => 'G', 'url' => 'action.php?action=g'),array('name' => 'H', 'url' => 'action.php?action=h'));$menu1 = array( array('title' => '高级1', 'item' => $item1),array('title' => '高级2','item' => $item2));
    $menu2 = array( array('title' => '高级3', 'item' => $item3),array('title' => '高级4','item' => $item4));$pmenu = array(array('class'=>'顶级1','menu'=>$menu1),array('class'=>'顶级2','menu'=>$menu2));
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>无标题文档</title>
    <script language="JavaScript">
    <!--
    function clickmenu(thisid){
    obj=eval(thisid);
    if(obj.style.display=="")
    obj.style.display='none';
    else
    obj.style.display='';
    }
    //-->
    </script> 
    </head><body>
    <?php 
    while(list($key,$class)=each($pmenu)){
    ?>
    <table width="150" border="1" cellspacing="0" bordercolor="#0066FF">
      <tr>
        <td onclick="clickmenu('<?php echo "menu".$key;?>')"><?php echo $class["class"]; ?></td>
      </tr>
      <tr>
        <td>
    <div id="<?php echo "menu".$key;?>" style="display:none">
    <?php 
    while(list($key1,$title)=each($class["menu"])){
    ?><table width="150" border="1" cellspacing="0" bordercolor="#0066FF">
            <tr>
              <td onclick="clickmenu('<?php echo "menu".$key."item".$key1;?>')"><?php echo $title["title"]; ?></td>
            </tr>
            <tr>
              <td>
      <div id="<?php echo "menu".$key."item".$key1;?>" style="display:none"><table width="150" border="1" cellspacing="0" bordercolor="#0066FF">
      <?php 
      while(list($key2,$name)=each($title["item"])){
      ?>
                  <tr>
                    <td><?php echo $name["name"]; ?></td>
                  </tr>
      <?php 
      }
      ?>
              </table></div>
      </td>
            </tr>
        </table>
    <?php 
    }
    ?></div>
    </td>
      </tr>
    </table>
    <?php 
    }
    ?>
    </body>
    </html>
      

  4.   

    首先用一个简单的函数来展开该树
    <pre>
    <?php
    $item1 = array( array('name' => 'A', 'url' => 'action.php?action=a'),array('name' => 'B', 'url' => 'action.php?action=b'));
    $item2 = array( array('name' => 'C', 'url' => 'action.php?action=c'),array('name' => 'D', 'url' => 'action.php?action=d'));
    $item3 = array( array('name' => 'E', 'url' => 'action.php?action=e'),array('name' => 'F', 'url' => 'action.php?action=r'));
    $item4 = array( array('name' => 'G', 'url' => 'action.php?action=g'),array('name' => 'H', 'url' => 'action.php?action=h'));$menu1 = array( array('title' => '高级1', 'item' => $item1),array('title' => '高级2','item' => $item2));
    $menu2 = array( array('title' => '高级3', 'item' => $item3),array('title' => '高级4','item' => $item4));$pmenu = array(array('class'=>'顶级1','menu'=>$menu1),array('class'=>'顶级2','menu'=>$menu2));function tree($menu,$open="",$deep=0) {
      foreach($menu as $k=>$v) {
    if(isset($v['class'])) { //顶级
    echo $v['class']."\n";
    if(empty($open)) tree($v['menu'],$open,$deep+1);
    }
    if(isset($v['title'])) { //高级
    echo str_repeat("\t",$deep).$v['title']."\n";
    if(empty($open)) tree($v['item'],$open,$deep+1);
    }
    if(isset($v['name'])) { //叶
    echo str_repeat("\t",$deep).$v['name']."[".$v['url']."]\n";
    }
      }
    }tree($pmenu);
    ?>
    参数
    $deep 表示树的深度
    $open 表示是否展开 函数中暂以空表示全部展开如果现在不想展开“顶级2-高级3”的叶节点,你计划如何表述这个条件呢?
    表述不同算法也不竟相同
    表面上看,可以用节点文字链作为识别标志,但有可能出现不唯一的情况
    若在的层次上加入标志所属层次的元素倒是一种解决方案,但你没有提出
    所以我说“条件不足”
      

  5.   

    呵呵,可能不行。里面还是用到了js.你用js来控制div的显示,如果用户点右键的话是可以查看到树的结构。这恰恰不是我想要的,那样的话更多的问题就出来了,要禁右键,要禁查看源代码,要禁Ctrl+n,要禁另存……,会累死的。:)
      

  6.   

    不好意思,我指的是kingerq(多菜鸟)
      

  7.   

    我到是有一个js+php的树型菜单。
    完全实现你的要求,要的话发信到[email protected]
      

  8.   

    to xuzuning(唠叨) 
    老大的函数的确不错,对于顶级2-高级3这一分支,应当是点击顶级2可以打开高级3,4,点高级3,4可以展开其叶。然后点各自节点可以收拢其下的所有分支。
    你所说的加入层次标志我还没有想到,所以没有提出,惭愧,如果要加,应当是如何来加,是否对每个数组都要加上这一标志。
    另外要保存结构似乎办法也有很多,1是全展开之后用js隐显,2是逐个展开用session或是文件来存,3是用get或session来获取参数列表,我现在用的是最后的一种,不知道有无更好的办法。
      

  9.   

    to pwtitle(doodoo)
    呵呵,js的树形菜单实在是太多了。我这里要的是不用js的,谢谢帮助。
      

  10.   

    为简化问题的讨论,并且也使函数更简洁。建议调整数据组织如下。可容纳的层次由允许使用内存为限
    <pre>
    <?php
    $item1 = array( array('text' => 'A', 'url' => 'action.php?action=a'),array('text' => 'B', 'url' => 'action.php?action=b'));
    $item2 = array( array('text' => 'C', 'url' => 'action.php?action=c'),array('text' => 'D', 'url' => 'action.php?action=d'));
    $item3 = array( array('text' => 'E', 'url' => 'action.php?action=e'),array('text' => 'F', 'url' => 'action.php?action=r'));
    $item4 = array( array('text' => 'G', 'url' => 'action.php?action=g'),array('text' => 'H', 'url' => 'action.php?action=h'));$menu1 = array( array('text' => '高级1', 'item' => $item1),array('text' => '高级2','item' => $item2));
    $menu2 = array( array('text' => '高级3', 'item' => $item3),array('text' => '高级4','item' => $item4));$pmenu = array(array('text'=>'顶级1','item'=>$menu1),array('text'=>'顶级2','item'=>$menu2));function tree($menu,$open="",$deep=0) {
      foreach($menu as $k=>$v) {
    if(isset($v['text'])) {
    echo str_repeat("\t",$deep).$v['text'];
    if(isset($v['url'])) echo "[".$v['url']."]";
    echo "\n";
    if(is_array($v['item']))
    if(empty($open)) tree($v['item'],$open,$deep+1);
    else
    if(in_array($open,$point)) tree($v['item'],$open,$deep+1);
    }
      }
    }tree($pmenu);
    ?>
      

  11.   

    to:ustb(偶然)
    你用纯php生成不闲效率低吗?每次点hit都要重新生成页面。不划算啊。
      

  12.   

    to pwtitle(doodoo)
    不到不得已我也不会这么干,只是js不太好设置权限,所以才想在服务器端来直接实现权限控制,当然我可能会用php生成对应的权限树之后再用js来控制显隐。不仅仅js可以控制表格的显隐,php也是可以做到的,谢谢你的提醒!:)
      

  13.   

    其实我的“树”类里的使用js的方案一样是在浏览器中看不见“结构”的纯php方案正在调试中。请稍候
      

  14.   

    <?php
    session_start();
    ?>
    <pre>
    方案一
    php版本4.3.2
    设由session保存节点状态信息
    初态:仅显示“顶级”节点
    <?php
    $item1 = array( array('text' => 'A', 'url' => 'action.php?action=a'),array('text' => 'B', 'url' => 'action.php?action=b'));
    $item2 = array( array('text' => 'C', 'url' => 'action.php?action=c'),array('text' => 'D', 'url' => 'action.php?action=d'));
    $item3 = array( array('text' => 'E', 'url' => 'action.php?action=e'),array('text' => 'F', 'url' => 'action.php?action=r'));
    $item4 = array( array('text' => 'G', 'url' => 'action.php?action=g'),array('text' => 'H', 'url' => 'action.php?action=h'));$menu1 = array( array('text' => '高级1', 'item' => $item1),array('text' => '高级2','item' => $item2));
    $menu2 = array( array('text' => '高级3', 'item' => $item3),array('text' => '高级4','item' => $item4));$pmenu = array(array('text'=>'顶级1','item'=>$menu1),array('text'=>'顶级2','item'=>$menu2));function tree($menu,$point=-1,$deep=0) {
      //构造状态信息
      static $info;
      static $num;
      if($deep == 0) {
    $info = array();
    $num = 0;
      }
      foreach($menu as $k=>$v) {
    $tmp = $v;
    unset($tmp['item']);
    $info[] = array(item=>$tmp,deep=>$deep,child=>(is_array($v['item'])?count($v['item']):0));
    if(is_array($v['item']))
    tree($v['item'],"",$deep+1);
      }
      if($deep != 0) return;  //至此已将数状的结构平面化了
      //print_r($info); // 查看平面化结果
      if(! isset($_SESSION['menu_info'])) { // 如果尚未定义菜单状态信息
    $menu_info = str_repeat("0",count($info));
    $_SESSION['menu_info'] = $menu_info;
      }else $menu_info = $_SESSION['menu_info'];
      echo "$menu_info\n"; //查看菜单状态信息  //调整菜单状态
      if($point >= 0) {
    $ch = $menu_info[$point]; //取得指定的节点的状态
    $menu_info[$point] = $ch = $ch=="1"?"0":"1"; //置反节点状态 $deep = $info[$point]['deep']; //取得当前的深度
    for($i=$point+1;$info[$i]['deep']>$deep;$i++) { //向深度方向
    $menu_info[$i] = "0"; //不管三七二十一,先关了再说
    }
    if($ch == "1") { //如果不是关闭
    for($i=$point+1;$info[$i]['deep']>$deep;$i++) { //向深度方向
    if($info[$i]['deep'] == $deep+1) {
    $menu_info[$i] = "1";
    }
    }
    }
    $_SESSION['menu_info'] = $menu_info; //保存修改
      }
      echo "$menu_info\n"; //再次查看菜单状态信息
      //显示菜单
      for($i=0;$i<strlen($menu_info);$i++)
    if($menu_info[$i] == "1" || $info[$i]['deep'] == 0) {
    echo str_repeat("\t",$info[$i]['deep']).$info[$i]['item']['text'];
    if(isset($info[$i]['item']['url']))
    echo "[".$info[$i]['item']['url']."]";
    else echo "($i)";
    echo "\n";
    }
    }tree($pmenu);
    tree($pmenu,0); //展开第一分支
    ?>
    不过这样写要被 mikespook(Mike大懒猫) 指责“不遵守软件工程的规范”了至于如何传递和接收参数就有你决定了
      

  15.   

    方案一
    php版本4.3.2
    设由session保存节点状态信息
    初态:仅显示“顶级”节点
    11001000000000
    11001000000000
    顶级1(0)
    高级1(1)
    高级2(4)
    顶级2(7)
    11001000000000
    00000000000000
    顶级1(0)
    顶级2(7)这是我运行后的效果,是这样吗?