2015-04-02 20 views
-1

我試圖在<select>元素中實現以下輸出。html <select>多個級別

Mouses 
    Logitech 
    Red 
    White 
    Microsoft 
    Black 

Keyboards 
    Logitech 
    Small size 
     Red 
     Green 
    Medium size 
     Black 

正如您所看到的,可能存在不定級別。 在我的MySQL數據庫我創建了一個表類

id 
description 
category_parent_id 

和輸入是非常簡單的。

1 Mouses  null 
2 Logitech  1 
3 Red   2 
4 White  2 
5 Keyboards null 
6 Logitech  5 

依此類推。正如你所看到的,當第一個類別被設置爲null來識別原點時。

// Disables duplicated categories 
$alreadyOutput = array(); 

foreach($categories as $category) 
{ 
    if(in_array($category->id, $alreadyOutput) == FALSE) 
    { 
     echo '<option value="' . $category->id . '">'; 
     echo $category->description; 
     echo '</option>'; 
    } 

    foreach($categories as $subCategory) 
    { 
     if($subCategory->category_parent_id == $category->id && 
      in_array($subCategory->id, $alreadyOutput) == FALSE) 
     { 
      echo '<option value="' . $subCategory->id . '">'; 
      echo '&nbsp;&nbsp;&nbsp;' . $subCategory->description; 
      echo '</option>'; 
     } 
    } 
} 

有了這個代碼我的輸出是:

Mouses 
    Logitech 
    Red 
    White 
    Microsoft 
    Black 

Keyboards 
    Logitech 
    Small size 
    Red 
    Green 
    Medium size 
    Black 

而且我明白這是爲什麼。 首先,空間&nbsp&nbsp&nbsp只做一次,應該根據級別增加。我試圖通過創建兩個函數來提出解決方案。第一個決定類別需要做的步驟數量以達到原點。

function stepsToJump($categories, $id, $category_parent_id) 
{   
    $parentPosition = 0; 
    $position  = 0; 

    foreach($categories as $i => $category) 
    { 
     if($category->id == $category_parent_id) 
      $parentPosition = $i; 

     if($category->id == $id) 
      $position = $i; 
    } 

    return $position - $parentPosition; 
} 

function htmlSpaces($amount) 
{ 
    $html = '&nbsp;&nbsp;&nbsp;'; // default 

    for($i = 0; $i < $amount; $i++) 
     $html .= '&nbsp;&nbsp;&nbsp;'; 

    return $html; 
} 

而與此,我以這種方式實現:

echo htmlSpaces(stepsToJump($categories, 
          $subCategory->id, 
          $category->id)) . $subCategory->description; 

可惜的是我的輸出是錯誤的。

Mouses 
    Logitech 
    Red 
     White 
    Microsoft 
    Black 

Keyboards 
    Logitech 
    Small size 
     Red 
      Green 
    Medium size 
     Black 
+3

FYI:有一種叫做'optgroup'的問題 – adeneo 2015-04-02 16:29:06

+0

問題是什麼?再讀一遍。 我不想使用'optgroup',因爲我希望用戶能夠選擇頭部類別。 – Linesofcode 2015-04-02 16:30:19

+2

@Linesofcode你沒有說你試圖避免'optgroup'。 – 2015-04-02 16:33:09

回答

0

我發現從頭開始編寫比調試代碼更容易。以下代碼正在按照您的預期工作。

$dbh = new PDO('---connection string---'); 

$stmt_categories = $dbh->prepare("SELECT * FROM categories"); 
$stmt_categories->execute(); 
$categories = $stmt_categories->fetchAll(PDO::FETCH_ASSOC); 
$allCategories = $categories; 

$lastParent = NULL; // we will use this variable to place categories under their parents. 

print '<select>'; 

while (count($categories) > 0) { // we use this control, because we will unset elements from $categories. until $categories array is empty, following foreach loop will run continously. 

    foreach ($categories as $i => $category) { 

     if ($category['category_parent_id'] == $lastParent) { // by using this control, we will be sure output starts with a top level category. 

      if ($category['category_parent_id'] == NULL) { 
       $indent = 0; // since this is a top level category, indent is 0. 
      } 

      print '<option value="' . $category['id'] . '">'; 
      print str_repeat('&nbsp;', ($indent)) . $category['description']; 
      print '</option>'; 

      if (hasChildren($categories, $category['id']) == TRUE) { 

       $lastParent = $category['id']; 
       $indent++; // this is a parent category. so, one of its children is coming on the next iteration. we incremented $indent to be inherited by the child. 

      } 

      unset($categories[$i]); 

     } else { 

      // ok, this category is not a child of our $lastParent. if all the children of $lastParent are unset from $categories array, this loop will continue forever. so, we are going to control if there are other children of $lastParent. 

      if (hasChildren($categories, $lastParent) == TRUE) { 

       continue; // there is still at least one child of $lastParent. it is ok to continue to next iteration. 

      } else { 

       // there are no (more) children of $lastParent. so, we need to manipulate this variable. let's check parent of $lastParent on the next iteration. 

       $lastParent = parentCategory($allCategories, $lastParent); 
       $indent--; 

      } 

     } 

    } 

} 

print '</select>'; 


function hasChildren($categories, $categoryID) { 

    foreach($categories as $i => $category) { 

     if ($category['category_parent_id'] === $categoryID) { 

      return TRUE; 

     } 

    } 

    return FALSE; 

} 

function parentCategory($categories, $categoryID) { 

    foreach ($categories as $i => $category) { 

     if ($category['id'] === $categoryID) { 
      return $category['category_parent_id']; 
     } 

    } 

}