php递归函数到内置菜单

时间:2014-03-14 10:28:10

标签: php recursion menu

我试图使用PHP构建递归菜单但没有成功

mysql表

menuid name parentid

和我的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>';
}

但是这个循环没有停止并产生错误的输出。它可以有子级别达到n级。我想让它变得动态cuz水平可能会在未来的任何建议中改变吗?

1 个答案:

答案 0 :(得分:0)

您的问题是您没有结构化结果来迭代。您可能会将SubElement 2 > 3 > 4作为第一个结果,但2 > 3 > 1作为第5个结果。所以你不能只重复一次结果并构建你的html。

你想做什么(appart from,switching to nested sets,这是你真正想要做的事情 wink )首先是你的结果。

迭代你的结果并构建一个嵌套数组来迭代迭代以构建你的HTML。找到&#34;把你的元素放在哪里&#34;在递归数组中,您还需要以递归方式检查现有数组。如果您存储的是id和parent id,那么在检查所有元素之前如何找出根元素是什么? 所以我可以编写代码来做到这一点,但我宁愿不这样做,因为无论如何它都是一个可怕的解决方案。 为了更有效地这样做,如果你不仅存储你的parentid而且也存储一个级别,那将真的有帮助。 然后,您可以将元素存储在存储每个级别的所有元素的二维数组中,然后递归地使用该数组。即。

$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;
}

现在你有一个像这样的数组:

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' ...)
    )
  )
)

现在你可以递归迭代这个数组,解决每个项目的每个级别到无穷大; - )

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

有些不想使用嵌套设置的人通常会存储pathes而不是父ID。 即:

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

迭代过程更容易(在性能方面更便宜)。你可以轻松地对它进行排序。但是,它带来了很多问题和限制。