如何显示类别和子类别?

时间:2012-01-04 21:26:53

标签: php mysql hierarchical-data

如何显示类别和子类别? 我在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); 

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

使用这样的结构,您需要首先为所选项构建查询,然后构造对所选项父项的查询。从本质上讲,您需要查询您拥有的每个级别的菜单,这些菜单应该是可见的。

这就是树关系的parent_id方案效率不高的原因。使用嵌套集(http://en.wikipedia.org/wiki/Nested_set_model)或物化路径(http://en.wikipedia.org/wiki/Materialized_pa​​th)会更好。如果您希望对项目进行一些更新,从长远来看,物化路径可能更容易处理 - 我个人更喜欢它,尝试过两者。

答案 2 :(得分:-1)

由于您只需要显示类别及其所有子类别,因此您不需要递归菜单构建,并且您当然不希望在数据库调用中进行递归。所以最基本的解决方案(一个文件中的所有代码)都是这样的:

<?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>";
 }