代码之家  ›  专栏  ›  技术社区  ›  Ronnie

创建嵌套ul li的php函数?

  •  0
  • Ronnie  · 技术社区  · 16 年前

    我正在尝试将一个小的CMS附加到我正在创建的网站上。不过,我遇到了一个小问题。CMS使用PHP函数插入菜单,这些PHP函数创建HTML。我希望使用的特定函数(treemenu)创建一个嵌套的ul li,然后可用于下拉菜单。但是,嵌套的ul li结构如下:

    <li>Projects (Menu Level 1)</li>
        <ul>
            <li>Project 1 (Menu Level 2)</li>
            <li>Project 2 (Menu Level 2)</li>
            <li>Project 3 (Menu Level 2)</li>
        </ul>
    <li>News (Menu Level 1)</li>
    <li>Contact (Menu Level 1)</li>
    

    在CSS中创建下拉菜单时,我认为菜单级别1 li应该像这样包装其子级:

    <li>Projects (Menu Level 1)
        <ul>
            <li>Project 1 (Menu Level 2)</li>
            <li>Project 2 (Menu Level 2)</li>
            <li>Project 3 (Menu Level 2)</li>
        </ul>
    </li>
    <li>News (Menu Level 1)</li>
    <li>Contact (Menu Level 1)</li>
    

    我以前从未使用过PHP,因此不知道如何更改函数以完成上述任务。我希望这是一个简单的改变。下面是输出第一个示例结构的PHP函数:

    function treemenu($generat=0) {
    global $pagenum, $menu, $selected, $extension, $set;
    $count=0;
    $out="\n";
    $intend=0;
    while($menu[$count][0] != "") {
        if(strpos($menu[$count][3],"#") === false) {
        if($menu[$count][2]=="0" && $intend==2) {
            $intend--;
            $out.="</ul>\n";
        }
        if($menu[$count][1]=="0" && $intend==1) {
            $intend--;
            $out.="</ul>\n";
        }
        if($menu[$count][1]!="0" && $intend<1) {
            $intend=1;
            $out.="<ul>\n";
        }
        if($menu[$count][2]!="0" && $intend<2) {
            $intend=2;
            $out.="<ul>\n";
        }
        $out.="<li class=\"LNE_menu\"><a ";
        if($menu[$count][4]==$selected['name'])
            $out.= 'class="selected" ';
        if(strpos($menu[$count][3],"*"))
            $out.='href="'.str_replace("*", "",$menu[$count][3]).'">';
        elseif($generat)
            $out.='href="'.$menu[$count][3].".".$set['extension'].'">';
        else
            $out.='href="'.$set['indexfile'].'?page='.$menu[$count][3].'">';
        $out.=$menu[$count][4]."</a></li>\n";
        }
        $count++;
    }
    return $out;
    }
    

    是否有人能告诉我正确的方向,如何使一级菜单项的结束li标签在后面立即包装ul,如第二个示例所示?

    5 回复  |  直到 11 年前
        1
  •  8
  •   Alister Bulman    16 年前

    这将是使用递归的一个很好的例子。数组(其中包含子数组)定义每个级别和一个函数循环,每当它发现要处理的新数组时都会调用它自己。只要函数适当清理(关闭 </li> & </ol> )基本上是自动的。

    <?php
    // I know which function I'd rather write....
    $tree = array('Projects (Menu Level 1)',
                  array('Project 1 (Menu Level 2)',
                        'Project 2 (Menu Level 2)',
                        'Project 3 (Menu Level 2)'),
                  'News (Menu Level 1)',
                  'Contact (Menu Level 1)');
    
    // now quake beneath the power of this fully operational recursive function!
    function olLiTree($tree)
    {
        echo '<ul>';
        foreach($tree as $item) {
            if (is_array($item)) {
                olLiTree($item);
            } else {
                echo '<li>', $item, '</li>';
            }
        }
        echo '</ul>';
    }
    olLiTree($tree);  // kick off from the top level
    
        2
  •  3
  •   OIS    16 年前

    你只需要一个简单的函数。

    function unorderedList($val)
    {
        if (is_array($val)) {
            return '<ul><li>' . 
                    implode('</li><li>', 
                        array_map('unorderedList', $val)) . 
                '</li></ul>';
        } else {
            return $val;
        }
    }
    

    测试代码:

    $menu = array('Projects (Menu Level 1)',
                  array('Project 1 (Menu Level 2)',
                        'Project 2 (Menu Level 2)',
                        'Project 3 (Menu Level 2)'),
                  'News (Menu Level 1)',
                  'Contact (Menu Level 1)');
    
    
    echo unorderedList($menu);
    
        3
  •  3
  •   John Rasch    16 年前

    看起来Topbit已经打败我了,但我的是 轻微地 不同之处在于,它不会直接将值回送到输出流,而是将其保存在一个变量中,您可以 echo 在您方便的时候:

    <?php
    
    function GenerateMenu($arr)
    {
        $output = "<ul>\n";
        foreach($arr as $val) {
            if (is_array($val)) {
                $output .= "<li>\n" . GenerateMenu($val, $output) . "</li>\n";
            }
            else {
                $output .= "<li>" . $val . "</li>\n";
            }
        }
        $output .= "</ul>\n";
        return $output;
    }
    
    $html = GenerateMenu($menu);
    
    ?>
    

    编辑:

    感谢Gumbo和Topbit,现在我已经安装了PHP,我已经测试了它,它工作得很好。

        4
  •  0
  •   Karina    15 年前

    我认为它输出正确的HTML结构。

    function GenerateMenu($arr)
    {
    foreach($arr as $val) {
        if (next($arr)) { $nextitem = current($arr); }
        if (is_array($val)) {
            $output .= "\n<ul>\n" . GenerateMenu($val, $output) . "</ul>\n</li>\n\n";
        }
        elseif (is_array($nextitem)) { $output .= "<li>" . $val; }
        else { $output .= "<li>" . $val . "</li>\n"; }
    }
    return $output;
    }
    $html = GenerateMenu($menu);
    echo("<ul>\n" . $html . '</ul>');
    

    与上述测试代码相同:

    $menu = array('Projects (Menu Level 1)',
              array('Project 1 (Menu Level 2)',
                    'Project 2 (Menu Level 2)',
                    'Project 3 (Menu Level 2)'),
              'News (Menu Level 1)',
              'Contact (Menu Level 1)');
    
        5
  •  0
  •   JxAxMxIxN Coderzelf    11 年前

    我使用php domdocument类编写了这个。它将使用一个简单易行的循环来创建您的列表,其长度和深度与您给出的列表相同。如果您希望它有条理,只需先向数据库请求按标题(或其他)排序的列表。 它假定您的查询对象数据包含在$menu类别中,并且至少具有->id->父级->标题的属性(根据需要更改)

    $dom = new DOMDocument();
    $dom->validateOnParse = true;
    $dom->loadHTML("<html>");
    
    
    $root = $dom->createElement('ul');
    $root->setAttribute('class', 'menu');
    $dom->appendChild($root);
    
    
    foreach($menu_categories as $count => $category){
        $pid = $category->parent_id;
        $parent = $dom->getElementById('simple-li-'.$pid);
    
        if($parent != null){
    
            $ul = $dom->getElementById('simple-ul-'.$pid);
    
            if($ul == null){
                $ul = $dom->createElement('ul');
                $ul->setAttribute('id', 'simple-ul-'.$pid);
                $parent->appendChild($ul);
            }
            $target = $ul;
    
        }else{ 
            $target = $root;
        }   
    
        $li = $dom->createElement('li', $category->title);
        $li->setAttribute('id', 'simple-li-'.$category->id);
        $target->appendChild($li);
    }
    
    echo $dom->saveHTML($root);
    return;
    

    这是评论版…

    /**
     * This is pure and simple PHP!
     * @author Jamin Szczesny - Mar 2014
     * Assuming you have a returned query list of related rows named... 
     *  $menu_categories (the list can be in any order)
     * and it has valid attributes of.. 
     * ->id (category id)
     * ->title  (category title\name)
     * ->parent_id (categories parent)
     * 
     */
    
    $dom = new DOMDocument();//create a document
    $dom->validateOnParse = true;//this is a must
    $dom->loadHTML("<html>");//you must load some valid html
    
    //add a root list to the dom
    $root = $dom->createElement('ul');
    $root->setAttribute('class', 'menu');
    $dom->appendChild($root);
    
    //loop through all of your category rows
    foreach($menu_categories as $count => $category){
        $pid = $category->parent_id;
        $parent = $dom->getElementById('simple-li-'.$pid);
    
        //see if we found a parent
        if($parent != null){ //parent found...
            //look for a ul within the parent
            $ul = $dom->getElementById('simple-ul-'.$pid);
    
            //check to see if that ul exists
            if($ul == null){//ul not created yet so create one
                $ul = $dom->createElement('ul');
                $ul->setAttribute('id', 'simple-ul-'.$pid);
                $parent->appendChild($ul);
            }
            $target = $ul;
    
        }else{ //no parent found...
            $target = $root;
        }   
        //create this list item
        $li = $dom->createElement('li', $category->title);
        $li->setAttribute('id', 'simple-li-'.$category->id);
        $target->appendChild($li);
    }
    //output only the html from our list
    echo $dom->saveHTML($root);
    return;