2011-09-29 253 views
2

我的想法很简单:if child-> indent,if parent-> make bold。PHP递归问题

比方说p0为P1和P2,P3和P4的母公司是P1的孩子的。 p5是像p0这样的独立页面。所以我想得到的是

p0 (bold font) 
[3px]p1(bold font) 
[ 6px ]p3 
[ 6px ]p4 
[3px]p2 
p5 (bold font) 

问题是,我想不通。如何实现我的想法。试过给定的功能。没有成功。它的工作原理,但只缩进一级孩子。我的递归PHP功能看起来像

function generateOptions($parent, $level, $padding, $db) 
{ 
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'"); 
    if($level == 0) {$padding=''; $optstyle='bold';} 
    else {$optstyle='std'; $padding=' ';} 
    while($data=$result->fetch_row()){ 
     echo generateOption($optstyle.'option', $data, $padding); 
     generateOptions($data[0], $level++, $padding, $db); 
    } 
} 

function generateOption($type,$data, $padding){ 
    switch($type){ 
    case 'boldoption': return '<option class="bold" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break; 
    case 'stdoption': return '<option class="std" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break; 
    } 
} 

这里是我的数据库表的截图。 http://prntscr.com/39461

最后的工作效果

function generateOptions($parent, $level, $padding, $db) 
{ 
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'"); 
    $spacer = '&nbsp;&nbsp;'; 
    $padding = str_repeat($spacer, $level); 
    while($data=$result->fetch_row()){  
     $children_html = generateOptions($data[0], $level+1, $padding, $db); 
     $optstyle = empty($children_html) ? 'std' : 'bold'; 
     $html .= generateOption($optstyle.'option', $level, $data, $padding); 
     $html .= $children_html; 
    } 
    return $html; 
} 

function generateOption($type, $level, $data, $padding){ 
    $bgcolor=array('0'=>'#f66e02','1'=>'#FF9C4D', '2'=>'#FF9C4D'); 
    $fontcolor=array('0'=>'#fff','1'=>'#000', '2'=>'#000'); 
    switch($type){ 
    case 'boldoption': return '<option class="bold" style="background-color:'.$bgcolor[$level].'; color:'.$fontcolor[$level].'" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break; 
    case 'stdoption': return '<option class="std" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break; 
    } 
} 

回答

2

你压痕问题,你可以很容易地通过像素数为一个简单的缩进(在你的情况的3px)的$level乘以解决。

对于bold问题,您需要一个不同的方法,因为在当前的代码,你不知道,如果该项目有任何孩子。解决这个问题的方法是首先将孩子放入一个变量中,然后添加bold样式(如果有的话),回应该项目,然后处理这些孩子。

就我个人而言,我会首先从数据库中获取所有数据,然后构建分层结构,然后使用不同的函数生成html。有关更多详细信息,请参见this question

编辑:根据您更新的问题;您可以轻松地优化它,摆脱在while循环查询(我还是会去的顺便把前一段选项...):

  • 不要echo什么,只是回报从功能
  • 一个字符串中的while功能摆脱查询
  • 交换echo和函数调用行

在你的函数的结果会是这样的:

.... 
$html = ''; 
while (...) 
{ 
    $children_html = generateOptions($data[0], $level+1, $padding, $db); 
    $optstyle = empty($children_html) ? 'std' : 'bold'; 
    $html .= generateOption($optstyle.'option', $data, $padding); 
    $html .= $children_html; 
} 
return $html; 

而只是做一个echo generateOptions(...)你在哪里调用函数。

+0

我无法弄清楚如何实现你已经发送到我的代码的链接 – demonoid

+0

有3个步骤:第一步你得到你的数据库信息在一个平面数组中,然后你在多维数组中变换这个平面数组(使用该递归函数的变体),然后你可以编写不同的(递归...)函数来生成html输出想要(或者只有一个用于你的“选项”) – jeroen

+0

我更新了我的问题请看看 – demonoid

1

看起来你可能需要增加更多的&nbps;“s到你那里填充你只是将其分配给一个空间。

else {$optstyle='std'; $padding='&nbsp;';} 

else {$optstyle='std'; $padding .='&nbsp;';} 
+0

它会缩进除第一个以外的所有级别。但我想缩进基于父母的孩子 – demonoid

0

您试图平坦的数据结构(列表)映射到一棵树视觉。

之前,你可以在一个简单的方式做到这一点,你需要收集是影响显示在列表中选择日期。

E.g.您可以为每个条目(1,2或3)添加level,这看起来就像是您的递归结构!

然后,你将修改后的列表中显示程序,只需要决定基于水平如何显示的条目,每个级别:

  1. font-weight: bold;
  2. padding-left: 3px; font-weight: bold;
  3. padding-left: 6px;

最简单的事情就是将类属性赋值给元素父HTML标记,如level-1level-2等。

你已经有一个$level可变的,但我看到一个错误,你增加它所有的时间,但你只需要通过值:

generateOptions($data[0], $level+1, $padding, $db); 

这可能是这个已经解决了你的问题。

+0

这对我来说并不明确。我们可以继续讨论Skype或任何其他IM? – demonoid

+0

我没有20个代表:( – demonoid

+0

你的昵称是什么? – demonoid