2012-01-04 193 views
-3

如何顯示類別和子類別? 我在DB中有一個表。排在這張表看起來是這樣的:如何顯示類別和子類別?

CREATE TABLE IF NOT EXISTS `category` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) NOT NULL, 
    `parent_id` int(11) NOT NULL, 
    `order` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM 

我想顯示類別和子類別喜歡上這個網站:http://www.dealsdirect.com.au/c/baby-1/(左側菜單)

我嘗試:

<?php 
include 'Category_model.php'; 
include 'Advert_model.php'; 
$nr = $_GET['id']; 

function show_category($nr){ 


    try 
     { 
      $pdo = new PDO('mysql:host=localhost;dbname=advert', 'root', ''); 
      $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

      $stmt = $pdo -> query("SELECT * FROM category where `parent_id` = $nr"); 


      echo "<ul>"; 

      foreach ($stmt as $row){ 
       echo "<li><a href=category_view.php?id={$row['id']}> {$row['name']}</a>".show_category($row['id'])."</li>"; 

       } 
       echo "</ul>"; 
       //$id = $_GET['id']; 
       } 






     catch(PDOException $e) 
       { 
      echo 'Error!: ' . $e->getMessage(); 

      } 

    } 

    show_category($nr); 
+0

那麼,最新的問題是什麼? – KingCrunch 2012-01-04 21:29:19

+0

我不知道該怎麼做。請「算法」/步驟怎麼辦 – user1050014 2012-01-04 21:32:34

回答

0

隨着像這樣的結構,您需要先爲所選項目構造一個查詢,然後再爲所選項目父項構造一個查詢。從本質上講,您需要查詢每個級別的菜單,這應該是可見的。

這就是樹狀關係的parent_id方案效率不高的原因。更好地使用嵌套集(http://en.wikipedia.org/wiki/Nested_set_model)或物化路徑(http://en.wikipedia.org/wiki/Materialized_pa​​th)。如果您希望對這些項目進行一些更新,從長遠來看,物化路徑可能會更容易處理 - 我個人更喜歡它,嘗試了兩者。

+0

根本沒有。您可以選擇所有行,理想情況下可以通過id對它們進行索引,然後遍歷並生成結果。 – 2012-01-04 21:56:40

+0

這是浪費資源,因爲你不需要所有的結果 - 可以隱藏大量的子類別項目,你不需要任何細節。除此之外,如果你有一個合適的結構,在php中遍歷和創建結果將比在數據庫中做得慢。 – Fake51 2012-01-05 09:09:48

1

下面的代碼應該讓你開始。這是一個「遞歸函數」 - 一個自我調用的函數。正如@ Fake51剛剛提到的那樣,它效率不高,但它應該可以工作。

您需要一些CSS來構建您製作的列表。

function showItems($parent = 0) { 
    $q = "SELECT id, name FROM category WHERE parent_id = $parent"; 
    $q = mysql_query($q); 
    if(mysql_num_rows($q)) { 
     echo "<ul>"; 
     while($r = mysql_fetch_row($q)) { 
      echo "<li>"; 
      echo "<a href=\"page.php?id=".$r[0]."\">".htmlentities($r[1])."</a>"; 
      showItems($r[0]); 
      echo "</li>"\n; 
     } 
     echo "</ul>\n"; 
    } 
} 
showItems(); 

編輯:既然還是有一直沒有公認的答案,這是我的修飾一個SQL查詢應該是更有效的,雖然有點更加混亂可能做這一切的代碼。看看它是如何爲你。

//Recursive function to show menu items from a passed in array 
function showItems(&$menu, $parent = 0) { 
    if(is_array($menu[$parent]) && sizeof($menu[$parent])) { 
     echo "<ul>"; 
     foreach($menu[$parent] as $num=>$name) { 
      echo "<li>"; 
      echo "<a href=\"page.php?id=".$num."\">".htmlentities($name)."</a>"; 
      showItems($menu, $num); 
      echo "</li>\n"; 
     } 
     echo "</ul>\n"; 
    } 
} 

//Create a multi-dimensional array of ALL menu items, separated by parent 
$menu = array(); 
$q = "SELECT id, name, parent_id FROM category ORDER BY order"; 
$q = mysql_query($q); 
while($r = mysql_fetch_row($q)) { 
    $menu[$r[2]][$r[0]] = $r[1]; 
} 

//Call the function 
showItems($menu); 
+0

你首先需要連接mysql_connect()並用mysql_select_db()選擇一個數據庫。如果需要,您應該可以將其轉換爲與PDO一起使用。 – SpoonNZ 2012-01-04 21:38:09

+0

謝謝。這很有幫助 – user1050014 2012-01-04 21:40:38

+0

這太可怕了。我寧願做一個選擇,獲得所有類別的數組,然後使用該數組。另外,如果您可以向類別表'has_children'添加另一個字段並存儲值,如yes/no或boolean,這將允許您使用更高效的算法 – 2012-01-04 21:54:24

-1

既然你只需要類別及其所有子類別顯示你不需要的菜單結構遞歸,你當然不希望在你的DB調用遞歸。所以最基本的解決方案(所有代碼在一個文件中)將是這樣的:

<?php 
include 'Category_model.php'; 
include 'Advert_model.php'; 

$pdo = new PDO('mysql:host=localhost;dbname=advert', 'root', ''); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$nr = $_GET['id']; 

$sql = 'SELECT * FROM category where `parent_id` = :id or `id` = :id'; 
$stmt = $pdo->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); 
$stmt->execute(array(':id' => $nr)); 
$menuCategories = $sth->fetchAll(); 

// If sub category id is passed fetch whole menu 
if ((1 == count($menuCategories)) && ($nr == $menuCategories[0]['id'])) { 
    $nr = $menuCategories[0]['parent_id']; 
    $stmt->execute(array(':id' => $nr)); 
    $menuCategories = $sth->fetchAll(); 
} 

$parentCategoryFormat = '<h5><a href="category_view.php?id=%s">%s</a></h5>'; 
$subCategoryFormat = '<li><a href="category_view.php?id=%s">%s</a></li>'; 
$parentCategoryHTML = ''; 
$subMenuHTML = ''; 
foreach ($menuCategories as $row) { 
    if ($row['id'] == $nr) { 
     $parentCategoryHTML = sprintf($parentCategoryFormat, $row['id'], htmlentities($row['name'])); // Render parent category 
    } else { 
     $subMenuHTML .= sprintf($subCategoryFormat, $row['id'], htmlentities($row['name'])); // Render subcategory 
    } 
} 

echo $parentCategoryHTML; 
if (!empty($subMenuHTML)) { 
     echo "<ul>{$subMenuHTML}</ul>"; 
} 
+0

當你點擊一個子類別時,$ nr將是該子類別的id,因此只獲取一行,而不是整個可見樹。 更不用說sql中失敗的引用以及代碼中的sql expoit向量。 – Fake51 2012-01-05 09:13:32

+0

@ Fake51注意,謝謝。我更新了代碼示例。我應該指出,即使這個更新的代碼不是生產質量,我只是想用這個代碼展示,在這個特定情況下,如果更復雜(更深)的菜單結構是不需要遞歸的,尤其是用DB查詢遞歸需要更好的解決方案,就像你在答案中提出的那樣改變'category'數據庫表結構。 – sbgoran 2012-01-05 21:53:50