2011-09-29 415 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