简体   繁体   English

PHP / MySQL - 构建导航菜单层次结构

[英]PHP/MySQL - building a nav menu hierarchy

So the final menu will look something like this: 所以最终菜单看起来像这样:

Item B
    Item B-1
        Item B-1-2
        Item B-1-1
Item A
    SubItem A-1
    SubItem A-2
Item C

Based on the following DB records: 基于以下DB记录:

id        menu_title          parent_menu_id    menu_level    weight
1         Item A                0                           1                     1
2         Item B                0                           1                     0
3         Item C                0                           1                     2
4         SubItem A-2       1                           2                     1
5         Item B-1             2                           2                     0
6         Item B-1-1          5                           3                     1
7         SubItem A-1       1                           2                     0
8         Item B-1-2          5                           3                     0

How would I go about displaying? 我该怎么去展示? My guess is it'll involve storing all the items into a multidimensional array, then looping through it somehow... 我的猜测是它将涉及将所有项目存储到一个多维数组中,然后以某种方式循环遍历它...

Hierarchical data is somewhat annoying in a relationsal database (excluding Oracle, which has operators in START WITH/CONNECT BY to deal with this). 在关系数据库中,分层数据有点烦人(不包括Oracle,它在START WITH/CONNECT BY有运算符来处理这个问题)。 There are basically two models : adjacency list and nested sets. 基本上有两种模型 :邻接列表和嵌套集。

You've chosen adjacency sets, which is what I typically do too. 你选择了邻接集,这也是我通常也会做的。 It's far easier to change than the nested set model, although the nested set model can be retrieved in the correct order in a single query. 尽管可以在单个查询中以正确的顺序检索嵌套集模型,但它比嵌套集模型更容易更改。 Adjacency lists can't be. 邻接列表不能。 You'll need to build an intermediate data structure (tree) and then convert that into a list. 您需要构建一个中间数据结构(树),然后将其转换为列表。

What I would do (and have done recently in fact) is: 我会做什么(事实上最近做过)是:

  • select the entire menu contents in one query ordered by parent ID; 在按父ID排序的一个查询中选择整个菜单内容;
  • Build a tree of the menu structure using associative arrays or classes/objects; 使用关联数组或类/对象构建菜单结构的树;
  • Walk that tree to create nested unordered lists; 走这棵树来创建嵌套的无序列表; and
  • Use a jQuery plug-in like Superfish to turn that list into a menu. 使用像Superfish这样的jQuery插件将该列表转换为菜单。

You build something like this: 你建立这样的东西:

$menu = array(
  array(
    'name' => 'Home',
    'url' => '/home',
  ),
  array(
    'name' => 'Account',
    'url' => '/account',
    'children' => array(
      'name' => 'Profile',
      'url' => '/account/profile',
    ),
  ),
  // etc
);

and convert it into this: 并将其转换为:

<ul class="menu">;
  <li><a href="/">Home</a></li>
  <li><a href="/account">Account Services</a>
    <ul>
      <li><a href="/account/profile">Profile</a></li>
...

The PHP for generating the menu array from is reasonably straightforward but a bit finnicky to solve. 用于生成菜单数组的PHP相当简单,但有点难以解决。 You use a recursive tree-walking function that builds the HTML nested list markup but will leave it's implementation as an exercise for the reader. 您使用递归树行走函数来构建HTML嵌套列表标记,但将其实现作为读者的练习。 :) :)

Dealing with the data structure as you have it will often involve recursion or multiple queries to build the tree. 处理数据结构时,通常会涉及递归或多个查询来构建树。

Have you considered other ways of storing a hierarchy? 您是否考虑过存储层次结构的其他方法? Check out modified pre-order traversal - here's a nice PHP based article about this . 查看修改后的预订遍历 - 这是一篇很好的基于PHP的文章

The way your storing hierarchical data isn't as efficient as you might want. 存储分层数据的方式不如您所希望的那样高效。 I read the article Managing Hierarchical Data in MySQL a few years ago and have since found it as the best solution to managing hierarchy based data in SQL. 几年前我读过MySQL中管理分层数据的文章并且发现它是在SQL中管理基于层次结构的数据最佳解决方案。 Next best benefit is that I believe you can grab the entire tree with one query. 下一个最大的好处是我相信你可以通过一个查询获取整个树。

I just posted in a similar question my own approach to transform MySQL hierarchical data (adjacency list) into a menu (HTML) 我刚刚发布了一个类似的问题我自己的方法将MySQL分层数据(邻接列表)转换为菜单(HTML)

It does not use recursion. 使用递归。 And it requires a single query to the database. 它需要对数据库进行单一查询

Read more at 了解更多信息

https://stackoverflow.com/questions/2871861#3368622 https://stackoverflow.com/questions/2871861#3368622

Thanks. 谢谢。

Another simple way you can generate hierarchy if you don't want to use nested sets is to use a simple text string in front. 如果您不想使用嵌套集,则可以生成层次结构的另一种简单方法是在前面使用简单的文本字符串。

Item B
    Item B-1
        Item B-1-2
        Item B-1-1
Item A
    SubItem A-1
    SubItem A-2
Item C

Would become 会成为

1 Item B
  1.1 Item B1
    1.1.1 Item B11
    1.1.2 Item B12
2 Item A
  2.1 Item A1
  2.2 Item B2
3 Item C

The digit in front of each item could be stored in a field and parsed based on length (representing the depth of where it is) to tell you everything you need to know about where it goes. 每个项目前面的数字可以存储在一个字段中,并根据长度(代表它的深度)进行解析,以告诉您需要了解的所有内容。

I use nested set hierarchies for more complicated stuff that requires calculation,e tc, but I find this approach has served well 我使用嵌套集层次结构来处理需要计算的更复杂的东西,但是我觉得这种方法很好用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM