关于用数组生成树形菜单的问题,请高手指教。

ustb 2004-01-09 03:01:11
$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))

现在是想用上面的数组生成如CSDN左侧的树形菜单,只能用php来实现,不能用js或xml。要求树形的每一个节点都能展开和收拢并互不影响。

生成的形式如
顶级1
|
|--高级1
| |
| |---A
| |---B
|
|--高级2
| |
| |---C
| |---D
|
顶级2
|
|--高级3
| |
| |---E
| |---F
|
|--高级4
| |
| |---G
| |---H

本想用函数来实现,没有成功,所以提到这里来了。敬请指教!
...全文
411 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
yunuo2010000 2004-06-18
  • 打赏
  • 举报
回复
学习
多菜鸟 2004-01-09
  • 打赏
  • 举报
回复
原来不能用js呀?不好意思,没有看清楚。
那我倒要看看高手们的代码了。
ustb 2004-01-09
  • 打赏
  • 举报
回复
to pwtitle(doodoo)
呵呵,js的树形菜单实在是太多了。我这里要的是不用js的,谢谢帮助。
ustb 2004-01-09
  • 打赏
  • 举报
回复
to xuzuning(唠叨)
老大的函数的确不错,对于顶级2-高级3这一分支,应当是点击顶级2可以打开高级3,4,点高级3,4可以展开其叶。然后点各自节点可以收拢其下的所有分支。
你所说的加入层次标志我还没有想到,所以没有提出,惭愧,如果要加,应当是如何来加,是否对每个数组都要加上这一标志。
另外要保存结构似乎办法也有很多,1是全展开之后用js隐显,2是逐个展开用session或是文件来存,3是用get或session来获取参数列表,我现在用的是最后的一种,不知道有无更好的办法。
pwtitle 2004-01-09
  • 打赏
  • 举报
回复
我到是有一个js+php的树型菜单。
完全实现你的要求,要的话发信到pwTitle@yahoo.com.cn
ustb 2004-01-09
  • 打赏
  • 举报
回复
不好意思,我指的是kingerq(多菜鸟)
ustb 2004-01-09
  • 打赏
  • 举报
回复
呵呵,可能不行。里面还是用到了js.你用js来控制div的显示,如果用户点右键的话是可以查看到树的结构。这恰恰不是我想要的,那样的话更多的问题就出来了,要禁右键,要禁查看源代码,要禁Ctrl+n,要禁另存……,会累死的。:)
xuzuning 2004-01-09
  • 打赏
  • 举报
回复
首先用一个简单的函数来展开该树
<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”的叶节点,你计划如何表述这个条件呢?
表述不同算法也不竟相同
表面上看,可以用节点文字链作为识别标志,但有可能出现不唯一的情况
若在的层次上加入标志所属层次的元素倒是一种解决方案,但你没有提出
所以我说“条件不足”
多菜鸟 2004-01-09
  • 打赏
  • 举报
回复
我这个你说可以吗??
多菜鸟 2004-01-09
  • 打赏
  • 举报
回复
<?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>
ustb 2004-01-09
  • 打赏
  • 举报
回复
http://www.posi.de的class.tree也用到了js
其实如果用js的话是很容易实现的,只要控制一下表格的显隐即可,这里要求用php来实现是为了彻底的隐藏不想显示东西,我已解决了在二维上的树形展开,不过用的办法不是递归,用递归的实现可能有点难,因为没有明确的父子关系在里面,而且这是维数上的深入,并不是可以无限分下去的,bluemeteor(挂月||╭∩╮(︶_︶)╭∩╮)提出的用session来存放节点列表的办法还没有试过,可以一试。
请教一下唠叨,如果要实现的话还需要哪些条件?你所说的指示分支的方案是否是指标识该节点的方案呢?
我现在是用get两个参数的办法来解决的,一个是action它的open和close用来打开和关闭树,另一个是expand它的值用来指向所开节点,不知道还有无更好的办法。
其实要实现这个问题的主要目的是要解决在服务器端实现权限树,即有相应的权限才能看到相应的树,我很笨,还请大家指点。
wubai250 2004-01-09
  • 打赏
  • 举报
回复

建议使用
http://www.posi.de的class.tree

比你做的好的多,而且要比csdn的好看,呵呵
bluemeteor 2004-01-09
  • 打赏
  • 举报
回复
先说一点

[要求树形的每一个节点都能展开和收拢并互不影响。]

这个有点困难 用session来记录目前处于打开状态的结点列表吧

讨论一哈
多菜鸟 2004-01-09
  • 打赏
  • 举报
回复
楼主的水平应该能解决这个问题吧。
xuzuning 2004-01-09
  • 打赏
  • 举报
回复
所给条件不足
一个递归函数就可全部展开,但你没有给出指示某个分支的方案
多菜鸟 2004-01-09
  • 打赏
  • 举报
回复
方案一
php版本4.3.2
设由session保存节点状态信息
初态:仅显示“顶级”节点
11001000000000
11001000000000
顶级1(0)
高级1(1)
高级2(4)
顶级2(7)
11001000000000
00000000000000
顶级1(0)
顶级2(7)

这是我运行后的效果,是这样吗?
ustb 2004-01-09
  • 打赏
  • 举报
回复
老大出手就是不一样,耽误你的时间了,感谢。
xuzuning 2004-01-09
  • 打赏
  • 举报
回复
<?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大懒猫) 指责“不遵守软件工程的规范”了

至于如何传递和接收参数就有你决定了
xuzuning 2004-01-09
  • 打赏
  • 举报
回复
其实我的“树”类里的使用js的方案一样是在浏览器中看不见“结构”的

纯php方案正在调试中。请稍候
ustb 2004-01-09
  • 打赏
  • 举报
回复
to pwtitle(doodoo)
不到不得已我也不会这么干,只是js不太好设置权限,所以才想在服务器端来直接实现权限控制,当然我可能会用php生成对应的权限树之后再用js来控制显隐。不仅仅js可以控制表格的显隐,php也是可以做到的,谢谢你的提醒!:)
加载更多回复(3)

21,891

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧