简体   繁体   English

PHP的递归功能,以建立菜单

[英]php recursive function to built menu

im trying to build recursive menu using PHP but not succeeding 我试图使用PHP构建递归菜单,但未成功

mysql table mysql表

menuid name parentid

and my php code 和我的PHP代码

function generateMenubar()
{
    $data = Yii::app()->db->createCommand("select * from menu");

    $result = $data->queryAll();        

    $html = '<ul class = "navigation">';

    foreach($result as $row)
    {
        if($row['parentid'] == "0")
        {
            $html .= '<li><a href="#"><span>'.$row["menuname"].'</span></a>';

            $menu_id = $row['menuid'];

            $html .= $this->generateHTML($result,$menu_id,$html);
        }
    }       

    return $html;
}

function generateHTML($result,$menu_id,$html)
{       
    foreach($result as $row_sub)
    {
        if($menu_id == $row_sub['parentid'])
        {
            $html .= '<ul><li><a href="buttons.html"><span>'.$row_sub['menuname'].'</span></a>';

            $menu_id = $row_sub['menuid'];
            $html .= $this->generateHTML($result,$menu_id,$html);
            $html .= '</li>';
        }           
    }
    return $html.'</ui>';
}

but this loop is not stopping and generating wrong output. 但是此循环不会停止并生成错误的输出。 it can have sub levels upto n level. 它最多可以具有n级子级。 i want to make it dynamic cuz levels may change in future any suggestion ? 我想使它的动态Cuz水平在将来可能有任何建议改变?

Your problem is that you do not have a structured result to iterate over. 您的问题是没有迭代的结构化结果。 You might have SubElement 2 > 3 > 4 as your first result but 2 > 3 > 1 as your 5th Result. 您可能将SubElement 2 > 3 > 4作为第一个结果,但将2 > 3 > 1作为第五个结果。 So you can't just iterate over the result once and build your html. 因此,您不能只遍历一次结果并生成html。

What you want to do (appart from, switching to nested sets , which is what you REALLY want to do wink ) is structure your result first. 您想要做的事情(从切换到嵌套集 ,这是您真正想做的眨眼 ),首先要构造您的结果。

Iterate over your result and build a nested array to iterate over recusively to build your HTML. 遍历您的结果并构建一个嵌套数组,以循环方式遍历以构建HTML。 To find "where to put your element" in your recursive array you need to recursively check back with your existing array always as well. 要在递归数组中找到“将元素放置在何处”,您还需要始终递归检查现有数组。 IF all you store is id and parent id, how to find out what the root element is before you checked ALL elements right? 如果您存储的所有内容都是id和parent id,那么在检查所有元素之前如何找出根元素是正确的? So i could write the code to do so, but i rather do not because it would be a horrible solution anyway. 所以我可以编写代码来这样做,但我宁愿不这样做,因为无论如何这将是一个可怕的解决方案。 To do so more efficiently it would really help if you do not only store your parentid but a level as well. 为了更有效地执行此操作,如果您不仅存储您的父代信息,还存储一个级别,那将真正有帮助。 Then you could store your elements in a two dimensional array storing all elements for each level and then recursively use that array. 然后,您可以将元素存储在二维数组中,该数组存储每个级别的所有元素,然后递归使用该数组。 ie

$navigationTempArray = array();
foreach($fakeMySQLResult as $row)
{
    if(!array_key_exists($row['level'], $navigationTempArray )) {
        $navigationTempArray[$row['level']] = array();
    }
    if(!array_key_exists($row['parentid'], $navigationTempArray[$row['level']] )) {
        $navigationTempArray[$row['level']][$row['parentid']] = array();
    }
    $navigationTempArray[$row['level']][$row['parentid']][] = $row;
}

now you have an array like this: 现在你有一个像这样的数组:

array (
  0 => array(
    'root' => array(
      1 => array('title' => 'Start' ...)
      2 => array('title' => 'Team' ...)
      3 => array('title' => 'Projects' ...)
    )
  ),
  1 => array(
    2 => array(
      4 => array('title' => 'Development' ...)
      5 => array('title' => 'Design' ...)
      6 => array('title' => 'Sales' ...)
    ),
    3 => array(
      7 => array('title' => 'Mayhem' ...)
      8 => array('title' => 'X' ...)
    )
  ),
  2 => array(
    4 => array(
      9 => array('title' => 'PHP' ...)
     10 => array('title' => 'MySQL' ...)
    )
  )
)

Now you can iterate over this array recursively, solving every level for every item to infinity ;-) 现在,您可以递归遍历此数组,将每个项目的每个级别求解为无穷大 ;-)

function returnSubNavigation($id,$level,$fullNavigationArray) {
$html = '';
if(array_key_exists($level, $fullNavigationArray) && array_key_exists($id, $fullNavigationArray[$level])) {
    $html .= '<ul>';
    foreach($fullNavigationArray[$level][$id] as $subElement) {
        $html .=  '<li><a href="#"><span>'.$subElement["menuname"].'</span></a>';
        $html .=  returnSubNavigation($subElement['id'], $level+1, $fullNavigationArray);
        $html .=  '</li>';
    }
    $html .= '</ul>';

}
return $html;

} }

echo returnSubNavigation('root', 0, $navigationTempArray);

Here is an online fiddle kind of thing that proves it works 这是一种在线小提琴,证明它是有效的

Some people who do not want to use nested sets often store pathes rather than parent id's. 一些不想使用嵌套集的人经常存储路径而不是父ID。 ie: 即:

| id   | path |
|    1 |    1 |
|    2 |    2 |
|    3 |  1.1 |
|    4 |  1.2 |
|    5 |  2.1 |
|    6 |    3 |

This is a lot easier (cheaper in terms of performance) to iterate over. 迭代起来很容易(就性能而言更便宜)。 You can sort it a lot easier. 您可以轻松地对其进行排序。 Still, it brings a lot of problems and restrictions. 尽管如此,它仍然带来许多问题和限制。

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

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