【问题标题】:Multi level menu with PHP使用 PHP 的多级菜单
【发布时间】:2013-05-08 21:01:06
【问题描述】:

我有一个这样的主题表:

id
title
parent_id
full_path

full_path 用于查找父级递归。像这样:

+----+-----------+-----------+-----------+
| id | title     | full_path | parent_id |
+----+-----------+-----------+-----------+
| 40 | home      | 40        |         0 |
| 41 | myhome1   | 41        |         0 |
| 42 | ****      | 40-42     |        40 |
| 43 | *****     | 41-43     |        41 |
| 44 | ***       | 44        |         0 |
| 45 | ****      | 45        |         0 |
| 46 | *****     | 46        |         0 |
| 49 | ******    | 49        |         0 |
| 50 | **** **   | 40-42-50  |        42 |
| 51 | **** **   | 40-42-51  |        42 |
| 52 | **** **   | 40-42-52  |        42 |
| 53 | *******   | 40-53     |        40 |
| 54 | ****      | 40-54     |        40 |
| 55 | ***       | 41-55     |        41 |
| 56 | **** **** | 40-42-56  |        42 |
| 57 | *******   | 44-57     |        44 |
+----+-----------+-----------+-----------+

我怎样才能得到这样的递归数组:

array
(
    40 => array
    (
        42 => array
        (
            50,51,52,etc.
        ),
        53,
        54
    )
    41 => array
    (
        43,
        55,
    ),
    44 => array
    (
        57,
    ),
    etc...
)

我可以使用full_path 创建多级菜单吗?

【问题讨论】:

  • 在我看来full_path 是多余的数据,所以我会从数据库中删除它。
  • 向我们展示您的尝试,我们可以看到您哪里出错了
  • @Voitcus 没有full_path 如何创建多级菜单?
  • 要遵循@Voitcus 所说的内容,您的 parent_id 需要是实际的父母,而不是其他祖先。让我们以#50 为例。目前#50full_path40-42-50,但在这种情况下,#42 应该是#50 的父级,#40 应该是#42 的父级。从#50 你会到达#42,从#42 你会到达#40 - 从那里你会停止循环,因为#40 没有父级。
  • 你在使用什么 DBMS?

标签: php arrays menu multi-level


【解决方案1】:

您可以使用下面的代码来执行此操作。请记住,这是可行的,因为您的主题数组将非常小,并且发生的递归将是最小的。不要在大型​​数组上使用这种方法。

<?php
$query = "SELECT id, parent_id FROM subjects";
//execute with your prefered method, eg mysqli

$rows = array();
while($row = $result->fetch_array(MYSQLI_ASSOC))
{
  $rows[] = $row;
}

function getChildren($p) {
  global $rows;
  $r = array();
  foreach($rows as $row) {
    if ($row['parent_id']==$p) {
      $r[$row['id']] = getChildren($row['id']);
    }
  }
  return $r;
}

$final = getChildren(0);
?>

【讨论】:

  • 如果我错了,请纠正我,但为什么不将查询放在 getChildren 函数中:这个查询可能会被 WHERE parent_id=$p 过滤所以,不必测试表的所有行.每个节点的一个查询是否比每个节点的“foreach on all rows”慢?
  • 我认为这些数字并不重要。如果您采用第二种方法,请确保您在 parent_id 上有一个索引。
【解决方案2】:

我编辑了 Hugo 的代码:

MySQL的代码:sqlfiddle

我们的桌子是这样的:

ID | Categories_name | Parent_id

我们的数据是(图片上的数字,显示id类别):

我们的 PHP 代码:

<?php
    $db=mysql_connect("127.0.0.1","root","");
    $db_name = "test";
    mysql_select_db($db_name,$db);


    $query = "SELECT `id`,`cat_name`,`parent_id` FROM `categories`";
    $result=mysql_query($query);
    $num=mysql_num_rows($result);

    $level_each_rows = array();
    $rows = array();
    for($i = 0 ; $i < $num ; $i++)
    {
        $q_data = mysql_fetch_array($result);
        $rows[] = $q_data;
    }

    function getChildren_string($p)
    {
        global $rows;
        global $level_each_rows;
        $r = array();
        $i = 0;
        $return = '';
        foreach($rows as $row)
        {
            if ($row['parent_id'] == $p)
            {
                if($row['parent_id'] == 0)
                {
                    $level_each_rows[$row['id']]['i'] = 0;
                }
                else
                {
                    $level_each_rows[$row['id']]['i'] = $level_each_rows[$row['parent_id']]['i'] + 1;
                }
                $return = $return.'
                <tr>
                    <td>'.$row['parent_id'].'</td>
                    <td><div style="margin:0px '.($level_each_rows[$row['id']]['i'] * 35).'px;">['.$row['id'].'] - '.$row['cat_name'].'</div></td>
                </tr>

                ';
                $return = $return.getChildren_string($row['id']);
                $i++;
            }
        }
        //---
        return $return;
    }

    $childs = getChildren_string(0);

    echo '
    <div dir="ltr">
        <table dir="ltr" border="1">
            <tr>
                <td>Parent ID</td>
                <td>Child ID</td>
            </tr>
    ';
    echo $childs;
    echo '
        </table>
    </div>
    ';
?>

结果:

【讨论】:

    猜你喜欢
    • 2012-07-09
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 2012-05-25
    相关资源
    最近更新 更多