如何让第一级别类别只显示一次?

时间:2011-10-14 14:41:49

标签: php mysql navigation categories

我在mysql中设置了一个表,如下所示:

我想创建一个带有父类别 - 子类别的侧边栏类别导航 - 以及我存储在另一个表格中的可能的第三级类别。

我试图让它们以这样的树结构显示:

夜晚

  • 俱乐部和社团
  • 公共房屋
  • 餐馆
  • 出租车和私人租车
  • 剧院和音乐厅
  • 酒吧

住宿

  • 住宿加早餐
  • 招待所
  • 假日住宿
  • 酒店
  • 自助式住宿

农业

  • 农业机械和备件
  • 农业商人
  • 动物饲料
  • 乡村服饰
  • 乳业

目前我可以创建以下内容:

使用此代码:

$dbc = mysql_connect($db_host,$db_user,$db_pass);
$sdb = mysql_select_db($db_database);

$query = 'SELECT category_name, subcategory_name FROM categories, subcategories WHERE subcategory_parent = category_name';

$result = mysql_query($query, $dbc)
or die (mysql_error($dbc));

while($row = mysql_fetch_array($result)) {

$catname = $row["category_name"];
$subcatname = $row["subcategory_name"];

echo "<li>$catname</li><ul><li>$subcatname</li></ul>";
}

我想让第一级别类别只显示一次,子类别位于下面的列表中。谁能告诉我最有效的方法呢?我想我需要使用foreach但不确定。

我设置的第三级类别表与此表具有相同的结构,但是是subsubcategory_id / subsubcategory_parent / subsubcategory_name。

3 个答案:

答案 0 :(得分:3)

仅在catname更改时输出。您还需要首先按category_name订购查询。

$row = mysql_fetch_array($result);
$catname = $row["category_name"];
$subcatname = $row["subcategory_name"];
$last = $catname;

echo "<li>$catname</li><ul>"

while($row = mysql_fetch_array($result)) {
    $catname = $row["category_name"];
    $subcatname = $row["subcategory_name"];
    if($last != $catname){
        echo "</ul><li>$catname</li><ul>"
    }
    echo "<li>$subcatname</li>";
    $last = $catname;
}
echo "</ul>";

编辑: 只需重新阅读这个问题,并想说当涉及到分层树时,使用父/子(或类/子/子子)并不是最好的方法。虽然它确实有效,但它通常需要多个查询和递归函数才能显示。更好的方法是使用为此目的而制作的nested set

答案 1 :(得分:1)

我认为你需要的是:

$cat_query = mysql_query("SELECT * FROM `TABLE_NAME` GROUP BY `subcategory_parent`") or die(mysql_error());

while($r_cat = mysql_fetch_array($cat_query)) {

    $cat_name = $r_cat['subcategory_parent'];

    echo("$cat_name<br />");

    $sub_cat_query = mysql_query("SELECT * FROM `subcategory_name` WHERE (`subcategory_parent` = '$cat_name')") or die(mysql_error());

    while($r_sub_cat = mysql_fetch_array($sub_cat_query)) {

        $sub_cat_name = $r_sub_cat['subcategory_name'];

        echo(" - $sub_cat_name<br />");

    }

    echo("<br />");

}

这可能是一种更有效的方法,这里的很多人在这方面知识渊博,但这应该可以解决问题!您可能还想检查,表名/列标题等,以确保它们与您的数据库匹配。

答案 2 :(得分:1)

如果您想要多层子类别(您可能已经说过),我会简化数据结构。我发现做这样的事情的最好方法是做一些与数据略有不同的事情:

category
+----+-----------+------------+----------------------------+
| id | parent_id | sort_order | name                       |
+----+-----------+------------+----------------------------+
| 1  | 0         | 0          | A Night Out                |
| 2  | 1         | 1          | Clubs and Societies        |
| 3  | 1         | 2          | Public houses              |
| 4  | 1         | 3          | Restaurants                |
| 5  | 1         | 4          | Taxis ...                  |
| 6  | 1         | 5          | Theatres ...               |
| 7  | 1         | 6          | Wine Bars                  |
| 8  | 0         | 0          | Accommodation              |
| 9  | 8         | 1          | Bed and Breakfast          |
| 10 | 8         | 2          | Guest Houses               |
| x  | x         | x          | ... and so on ...          |
+----+-----------+------------+----------------------------+

注意:我使用sort_order对具有相同父级的子节点进行排序。

现在我创建一个非常简单的SQL查询来检索parent_id然后sort_order排序的数据:

SELECT category.id, category.parent_id, category.name FROM category ORDER BY category.parent_id ASC, category.sort_order ASC

现在来了“有趣”部分...因为,实际上,我们想要的是结构化数据,所以我将查询传递到XML DOMDocument()以创建结构化类别系统

基本上,您循环遍历数据,当您正在执行该循环时,您可以创建ID为node_{$category_id}的节点,然后您可以按正确的顺序将子节点分配给其父节点。然后,您可以使用标准DOM导航来检索所需的数据树。

这样做的最大优点是,您可以从任何子节点开始,然后向后移动节点树以创建类别列表 - 这意味着您可以将其展开和折叠。

我最近写了一个更详细的解释;如果您愿意,我可以发布链接。