Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 多级菜单编程输出问题_Php_Menu_Multi Level - Fatal编程技术网

Php 多级菜单编程输出问题

Php 多级菜单编程输出问题,php,menu,multi-level,Php,Menu,Multi Level,我试图用php制作一个多级菜单,但是我不能正确地输出html 首先,我从数据库中提取数据,在“sort_id”和“id”之后对其排序,并将其存储到数组中 数据库结构: id | parent_id | sort_id | title --------------------------------- 1 | 0 | 0 | test1 2 | 1 | 1 | test2 3 | 1 | 0 | test3

我试图用php制作一个多级菜单,但是我不能正确地输出html

首先,我从数据库中提取数据,在“sort_id”和“id”之后对其排序,并将其存储到数组中

数据库结构:

id | parent_id | sort_id | title
---------------------------------
1  |     0     |    0    | test1
2  |     1     |    1    | test2
3  |     1     |    0    | test3
4  |     0     |    1    | test4
5  |     2     |    0    | test5
PHP代码

function hasChildren( $id, $data ) {
  foreach  ($data as $d ) {
    if ( $d['parent_id'] == $id ) {
        return true;
        break;
    }
  }
}

function menu ($arr) {
  foreach ( $arr as $d ) {
    if( is_array($d) && $d['parent_id'] == 0 ) {
        echo "<li><a href={$d['link']}>{$d['title']}</a>";
        if ( hasChildren ($d['id'], $arr) ) echo "<ul>";
    }

    foreach ( $arr as $row ) {
       if ( is_array($row) ) {

            if( $row['parent_id'] == $d['id'] ) {
                if ( hasChildren ($row['id'], $arr) ) {
                    echo "<li><a href={$row['link']}>{$row['title']}</a><ul>";
                } else echo "<li><a href={$row['link']}>{$row['title']}</a>";

                menu($row);

                if ( hasChildren ($row['id'], $arr) ) {
                    echo "</ul></li>";
                } else echo "</li>";
            }
        }
    }
    if ( is_array($d) && $d['parent_id'] == '0' ) {
        if ( hasChildren ($d['id'], $arr) ) echo "</ul>";
        echo "</li>";
    }
  }
}
函数有子项($id,$data){
foreach($d数据){
如果($d['parent_id']==$id){
返回true;
打破
}
}
}
功能菜单($arr){
外汇($arr作为$d){
if(is_数组($d)&&$d['parent_id']==0){
回声“
  • ”; 如果(hasChildren($d['id',$arr))回显“
      ”; } foreach($arr作为$row){ if(is_数组($row)){ 如果($row['parent_id']==$d['id']){ 如果(有子项($row['id'],$arr)){ 回声“
      • ”; }否则回声“
      • ”; 菜单(行); 如果(有子项($row['id'],$arr)){ 回声“
    • ”; }else回声“”; } } } if(is_数组($d)&&$d['parent_id']=='0'){ if(haschilds($d['id',$arr))回显“
    ”; 回声“
  • ”; } } }
    HTML输出

    <li>
       <a href="http://localhost">test1</a>
       <ul>
          <li><a href="http://localhost/2">test3</a></li>
          <li><a href="http://localhost/1">test2</a>
          <ul></ul>
          </li>
       </ul>
    </li>
    <li><a href="http://localhost/5">test5</a></li>
    <li><a href="http://localhost/4">test4</a></li>
    
    • 在“test2”打开和关闭“ul”标签之后

      “test5”应该是“test2”的子级,而不是父级

      我知道这可能不是最好的方法,但任何人都可以告诉我我做错了什么?

      1)菜单($row);它是无用的,因为它什么也不做

      2) 如果要应用递归,必须这样编写:

      function menu($arr, $parent) {
          $open = 0;
          foreach ($arr as $row) {
              if ($parent == $row['parent_id']) {
                  echo ($open?'':'<ul>')."<li><a href={$row['link']}>{$row['title']}</a>";
                  menu($arr, $row['id']);
                  echo "</li>";
                  $open++;
              }
          }
          if ($open) {
              echo "</ul>";
          }
      }
      
      menu($array, 0);
      
      功能菜单($arr,$parent){
      $open=0;
      foreach($arr作为$row){
      如果($parent==$row['parent\u id'])){
      echo($open?“”:“
        ”)“
      • ”; 菜单($arr,$row['id']); 回声“
      • ”; $open++; } } 若有($未结){ 回声“
      ”; } } 菜单($array,0);
      如果您可以更改数据库表,我强烈建议您使用MPTT(修改的预订单树遍历)存储数据。它解决了很多问题**,这是一个非常好的例子:

      CakePHP人员使用MPTT与父id字段相结合

      假设您不能或不想更改您的数据库,我将使用PHP对数据进行预排序,以便子对象在数组中位于其父对象之后,然后输出菜单。我开始使用uasort编写一些测试代码,但逻辑很快就变得混乱起来

      如果您选择MPTT,请接受答案;如果您需要第二种解决方案的帮助,请添加注释


      **-节点深度、到节点的路径、整个树都很容易派生,并且已经有代码可以这样做。

      oh my。。那太容易了。。我简直不敢相信我浪费了两天的时间在思考如何做这件事,而且是如此简单和更有意义。。非常感谢你。。是echo($open?“”:“
        ”)而不是echo($open?“
          ”:“”)它的意思是
          如果($open){/*echo nothing*/}其他{echo'
            ”;}
          我修复了它,请重新检查+1,非常感谢。我会留意的,因为这对我来说是新东西。但现在@Alexandr的答案是我需要的,我同意。需要注意的一点是,他的解是O(n^2)解。对于用户群或数据集较小的应用程序来说,这不是什么大问题。如果我使用递归,我会使用它通过合并排序对数据进行重新排序,这是一个O(log(n))解决方案(或者更好的方法是使用uasort,它允许您只关注比较器)。我在“企业”级软件中看到这种O(n^2)解决方案的次数真是太惊人了(在我上一份合同中删除了其中一个解决方案后,web服务调用速度提高了10000%)。