2012-01-04 197 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