在Smarty中构建无递归函数的无限级别菜单


Build unlimited level of menu without recursive function in Smarty

我能够生成输出为:

Cat1
SubCat1
SubCat3

但是我需要输出为

Cat1
Subcat1
 SubCat2
SubCat3

为了构建我的菜单,我使用数据库结构为:

site_id | parent_id    | site_name    | site_url  | Level
1       | 0            | Category 1   |example.com|   0
2       | 1            | Sub Cat 1    |example.com|   1
3       | 2            | Sub Cat 2    |example.com|   2
4       | 1            | Sub Cat 3    |example.com|   1

我可以将我的数组生成为:

Array ( 
    [0] => Array ( 
        [0] => 63 
        [site_id] => 63 
        [1] => 0 
        [parent_id] => 0
        [2] => Category 1 
        [site_name] => Category 1 
        [3] => Link1 
        [site_url] => Link1 
        [4] => 0 
        [level] => 0 
        [children] => Array ( 
            [0] => Array ( 
                [0] => 66 
                [site_id] => 66 
                [1] => 63 
                [parent_id] => 63 
                [2] => Sub Cat 3 
                [site_name] => Sub Cat 3 
                [3] => 
                [site_url] => 
                [4] => 1
                [level] => 1 
                [children] => Array ( ) 
            ) 
            [1] => Array ( 
                [0] => 64
                [site_id] => 64 
                [1] => 63 
                [parent_id] => 63 
                [2] => Sub Cat 1
                [site_name] => Sub Cat 1 
                [3] => 
                [site_url] => 
                [4] => 2 
                [level] => 2
                [children] => Array ( 
                    [0] => Array ( 
                        [0] => 65 
                        [site_id] => 65 
                        [1] => 64 
                        [parent_id] => 64 
                        [2] => Sub Cat2 
                        [site_name] => Sub Cat2 
                        [3] =>
                        [site_url] => 
                        [4] => 1 
                        [level] => 1 
                        [children] => Array ( ) 
                    ) 
                ) 
            ) 
        ) 
    )
)

使用的函数来自:https://stackoverflow.com/a/2795069/1137983.我只使用了后中的getTopCategories()和getCategories函数

为了生成输出,我使用:

{foreach from=$sitemap item=c name=sitemap}
 {if $c.level==0 }
<li><h2><a title="{$c.site_name}" href="{$c.site_url}">{$c.site_name}</a></h2><ul>
    {foreach item=d from=$c.children name=sitemap} 
<li><a title="{$d.site_name}" href="{$d.site_url}">{$d.site_name}</a></li>
    {/foreach}
{else}  
<li><h2><a title="{$c.site_name}" href="{$c.site_url}">{$c.site_name}</a></h2><ul>
{/if}
</ul>
</li>
{/foreach}  
</ul>

您可以尝试使用它-这是SiMan CMS的一部分,但您可以简单地根据您的数据结构更改它:

    function siman_load_menu($menu_id, $maxlevel=-1)
        {
            global $nameDB, $lnkDB, $_servervars, $tableprefix, $_settings, $special;
            $i=0;
            $addsql='';
            if ($maxlevel>=0)
                $addsql.=' AND submenu_from=0 ';
            $sql="SELECT * FROM ".$tableprefix."menu_lines WHERE id_menu_ml=".intval($menu_id)." $addsql ORDER BY submenu_from, position";
            $result=database_db_query($nameDB, $sql, $lnkDB);
            while ($row=database_fetch_object($result))
                {
                    $menu[$i]['id']=$row->id_ml;
                    $menu[$i]['mid']=$menu_id;
                    $menu[$i]['pos']=$row->position;
                    $menu[$i]['add_param']=$menu_id.'|'.$row->id_ml;
                    $menu[$i]['level']=1;
                    $menu[$i]['submenu_from']=$row->submenu_from;
                    $menu[$i]['sublines_count']=0;
                    $menu[$i]['url']=$row->url;
                    $menu[$i]['caption']=$row->caption_ml;
                    $menu[$i]['partial']=$row->partial_select;
                    $menu[$i]['alt']=$row->alt_ml;
                    $menu[$i]['attr']=$row->attr_ml;
                    $menu[$i]['newpage']=$row->newpage_ml;
                    $line_id=$row->id_ml;
                    $i++;
                }
            $maxlev=0;
            for ($i=0; $i<count($menu); $i++)
                {
                    $pos[$i]=0;
                }
            $fistlevelposition=0;
            $fistlevellastposition=0;
            for ($i=0; $i<count($menu); $i++)
                {
                    if ($menu[$i]['submenu_from']==0)
                        {
                            $maxpos=0;
                            for ($j=0; $j<count($menu); $j++)
                                if ($maxpos<$pos[$j])
                                    $maxpos=$pos[$j];
                            $pos[$i]=$maxpos+1;
                            $fistlevelposition++;
                            $menu[$i]['submenu_position']=$fistlevelposition;
                            $fistlevellastposition=$i;
                        }
                    else
                        {
                            $rootpos=0;
                            $childpos=-1;
                            for ($j=0; $j<count($menu); $j++)
                                {
                                    if ($menu[$j]['id']==$menu[$i]['submenu_from'])
                                        {
                                            $rootpos=$pos[$j];
                                            $menu[$i]['level']=$menu[$j]['level']+1;
                                            $menu[$j]['sublines_count']++;
                                            $menu[$j]['is_submenu']=1;
                                            $menu[$i]['submenu_position']=$menu[$j]['sublines_count'];
                                        }
                                    if ($menu[$j]['submenu_from']==$menu[$i]['submenu_from'] && $j!=$i && $childpos<$pos[$j])
                                        $childpos=$pos[$j];
                                }
                            $pos[$i]=($rootpos>$childpos) ? ($rootpos+1) : ($childpos+1) ;
                            for ($j=0; $j<count($menu); $j++)
                                {
                                    if ($pos[$j]>=$pos[$i] && $j!=$i)
                                        $pos[$j]++;
                                }
                        }
                }
            if (count($menu)>0)
                {
                    $menu[0]['first']=1;
                    $menu[$fistlevellastposition]['last']=1;
                }
            for ($i=0; $i<count($menu); $i++)
                {
                    $rmenu[$pos[$i]-1]=$menu[$i];
                }
            return $rmenu;
        }

在输出中,您将获得一个带有键level的数组,该键定义了菜单项的级别。

{section name=i loop=$menu}
{if $smarty.section.i.index eq 0}{else}<br>{/if}
{section name=j loop=$menu[i].level start=1} - {/section}
<a href="{$menu[i].url}" >{$menu[i].caption}</a>
{/section}