2012-09-05 99 views
5

我有一堆類別的數據庫,有些孩子:創建一個遞歸目錄樹功能

Array 
(
    [0] => Array 
     (
      [id] => 1 
      [name] => Home Improvement 
      [slug] => Home-Improvement 
      [parent] => 
      [user_id] => 1 
      [order] => 1 
     ) 

    [1] => Array 
     (
      [id] => 2 
      [name] => Asbestos Abatement & Removal 
      [slug] => Asbestos-Abatement-Removal 
      [parent] => 1 
      [user_id] => 1 
      [order] => 8 
     ) 

    [2] => Array 
     (
      [id] => 3 
      [name] => Asphalt & Asphalt Products 
      [slug] => Asphalt-Asphalt-Products 
      [parent] => 1 
      [user_id] => 1 
      [order] => 9 
     ) 

    [3] => Array 
     (
      [id] => 4 
      [name] => Bathroom 
      [slug] => Bathroom 
      [parent] => 1 
      [user_id] => 1 
      [order] => 10 
     ) 

    [4] => Array 
     (
      [id] => 5 
      [name] => Kitchen Cabinets 
      [slug] => Kitchen-Cabinets 
      [parent] => 1 
      [user_id] => 1 
      [order] => 11 
     ) 

    [5] => Array 
     (
      [id] => 6 
      [name] => Ceilings 
      [slug] => Ceilings 
      [parent] => 1 
      [user_id] => 1 
      [order] => 12 
     ) 

    [6] => Array 
     (
      [id] => 7 
      [name] => Cleaning 
      [slug] => Cleaning 
      [parent] => 1 
      [user_id] => 1 
      [order] => 13 
     ) 

    [7] => Array 
     (
      [id] => 8 
      [name] => Closet Organizers & Accessories 
      [slug] => Closet-Organizers-Accessories 
      [parent] => 1 
      [user_id] => 1 
      [order] => 14 
     ) 

    [8] => Array 
     (
      [id] => 9 
      [name] => Concrete 
      [slug] => Concrete 
      [parent] => 1 
      [user_id] => 1 
      [order] => 15 
     ) 

    [9] => Array 
     (
      [id] => 10 
      [name] => Contractors & Service Providers 
      [slug] => Contractors-Service-Providers 
      [parent] => 1 
      [user_id] => 1 
      [order] => 16 
     ) 

我試圖輸出是這樣的:

<ul> 
    <li>Parent 
     <ul> 
      <li>Child</li> 
     </ul> 
    </li> 
    <li>Parent with no Children</li> 
</ul> 

我試圖在PHP中構建遞歸樹腳本,但我被卡住了。這是迄今爲止我所擁有的。我堅持要在else和endif之間做些什麼。在foreach。 (我使用這種語法只是爲了方便閱讀。)任何建議?

echo $this->categories->makeTree(0, $this->db->get('categories')->result_array()); 

public static function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return ''; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 
     else: 

     endif; 
    endif; 

    $output .= '</li>'; 
    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 

編輯1

我能得到這個工作,雖然我有一個foreach循環,這可能不是最好的主意,一個數據庫調用:

public function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $subcategories = ci()->db->get_where('categories', array('parent' => $value['id'])); 

      if ($subcategories->num_rows() > 0): 
       $output .= $this->makeTree($value['id'], $subcategories->result_array()); 
      endif; 
     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 

編輯2

這是我的最終解決方案,重用數組,而不是做一個DB曲線紅黴素:

public function makeTree($parent, $array) 
{ 
    if (!is_array($array) OR empty($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $matches = array(); 

      foreach($array as $subkey => $subvalue): 
       if ($subvalue['parent'] == $value['id']): 
        $matches[$subkey] = $subvalue; 
       endif; 
      endforeach; 

      $output .= $this->makeTree($value['id'], $matches); 

     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 

    return $output; 
} 
+0

它目前遍歷2個級別。我們可以將它遍歷到n級嗎? –

回答

7

雖然這似乎回答,看看here。使用顯示的功能,只需一次迭代就可以將平面數據轉換爲嵌套數據。從嵌套數據創建一個ul列表非常簡單。例如:

function nested2ul($data) { 
    $result = array(); 

    if (sizeof($data) > 0) { 
    $result[] = '<ul>'; 
    foreach ($data as $entry) { 
     $result[] = sprintf(
     '<li>%s %s</li>', 
     $entry['name'], 
     nested2ul($entry['children']) 
    ); 
    } 
    $result[] = '</ul>'; 
    } 

    return implode($result); 
} 

echo nested2ul(array(flat2nested($yourFlatData)); 

這種方法的好處是,你不必在輸入數據一次又一次重新迭代只是爲了找孩子的元素。

+0

我喜歡這一點,但我一直在'return $ m [$ r] [0]得到「Undefined offset:0」。 '在makeRecursive函數中。這個函數需要像array(array('id'=> 5273,'parent'=> 0))',而我的數組是'Array([0] => Array([id] => 1,[parent ] => 0))'。任何關於如何解決這個問題的建議? – dallen

+0

@dallen您發佈的兩個片段實際上是相同的。我想問題是你的根父值是一個空字符串。而輔助函數使用'0'(參見'$ r'參數)。一個空字符串作爲數組鍵是有點問題,所以如果你可以改變你的輸入數據,我認爲其餘的應該工作。 – Yoshi

0

試試這個:

$cats = $this->db->get('categories')->result_array(); 

echo $this->categories->makeTree(0, $cats); 

public static function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return ''; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 
     else: 

     endif; 
    endif; 

    $output .= '</li>'; 

    $output .= $this->categories->makeTree($value['parent'], $cats); 

    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 
+0

不起作用。我只是得到一個500錯誤的頁面。 – dallen

1

我usualy使用這樣的事情,請注意

1日這一段代碼使用過時mysql_ *

第二個你應該有一個名爲level的數據庫字段,如果爲NULL,那麼它是主類別,如果它有一個數字,則它是具有該n的類別的子類別作爲編號

function getFamilies($level = 0) { 
    $level++; 
    $sql = "SELECT id from families WHERE level IS NULL"; 
    if (mysql_num_rows($result) > 0) { 
     echo "<ul>"; 
      while($row = mysql_fetch_assoc($result)) { 
       echo "<li>".$row['id']; 
        getSubFamilies($level, $row['id']); 
       echo "</li>"; 
      } 
     echo "</ul>"; 
    } 
} 

function getSubFamilies($level, $id) { 
    $level++; 
    $sqlSubFamilies = "SELECT id FROM families WHERE level = ".$id.""; 
    $resultSubFamilies = mysql_query($sqlSubFamilies); 
    if (mysql_num_rows($resultSubFamilies) > 0) { 
     echo = "<ul>"; 
      while($rowSubFamilies = mysql_fetch_assoc($resultSubFamilies)) { 
       echo "<li>".$rowSubFamilies['id']; 
        getSubFamilies($level, $rowSubFamilies['id']); 
       echo "</li>"; 
      } 
     echo "</ul>"; 
    } 
} 

getFamilies($level = 0); 
+0

在你的情況下,級別是父級,所以「選擇ID,父母爲空的類別的名稱」 – Pluda

2

這是我最後的解決方案,重複使用數組,而不是做一個數據庫查詢。如果您確實有更好的解決方案,請發佈!

public function makeTree($parent, $array) 
{ 
    if (!is_array($array) OR empty($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $matches = array(); 

      foreach($array as $subkey => $subvalue): 
       if ($subvalue['parent'] == $value['id']): 
        $matches[$subkey] = $subvalue; 
       endif; 
      endforeach; 

      $output .= $this->makeTree($value['id'], $matches); 

     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 

    return $output; 
} 
0

我覺得這個方法使用匿名函數很簡單。

//--------------------------- PRINT NESTED CATEGORIES 
$cats_childs = array(); 

$q = $db->query("SELECT id, parent, name FROM categories"); 

while ($r = $db->row($q)) 
{ 
    $cats_childs[$r['parent']][$r['id']] = $r; 
} 

$nested2ul = function($data) use (&$nested2ul, &$cats_childs) { 
    if (!empty($data)) { 
     echo '<ul>'; 
     foreach ($data as $r) { 
      echo '<li>'; 
      echo $r['name']; 
      $flat2ul($cats_childs[$r['id']]); 
      echo '</li>'; 
     } 
     echo '</ul>'; 
    } 
}; 

echo $nested2ul($cats_childs[0]);