Функция PHP, которая создает вложенный ul li? - PullRequest
0 голосов
/ 16 апреля 2009

Я пытаюсь прикрепить небольшую CMS к веб-сайту, который я создаю. Однако я столкнулся с небольшой проблемой. CMS использует функции PHP для вставки меню, эти функции PHP создают HTML. Конкретная функция, которую я хочу использовать (treemenu), создает вложенный язык, который затем можно использовать для выпадающего меню. Однако вложенный 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 элемента меню уровня 1 сразу после него, как во втором примере?

Ответы [ 5 ]

8 голосов
/ 16 апреля 2009

Это был бы отличный пример использования рекурсии. Массив (с вложенными массивами внутри него) определяет каждый уровень, и функция выполняет цикл, вызывая себя всякий раз, когда находит новый массив для обработки. Пока функция очищается соответствующим образом (закрывая </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
3 голосов
/ 16 апреля 2009

Простая функция - все, что вам нужно.

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 голосов
/ 16 апреля 2009

Похоже, 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);

?>

Edit:

Спасибо Gumbo и Topbit, теперь, когда я нахожусь на моей машине с установленным PHP, я проверил его, и он отлично работает.

0 голосов
/ 06 марта 2014

Я написал это, используя класс PHP DOMDocument. Он создаст ваш список столь же длинным и глубоким, как и список, который вы ему дадите, используя один простой и понятный цикл. Если вы хотите, чтобы это было организовано, просто попросите вашу базу данных сначала отсортировать список по названию (или как угодно). Предполагается, что данные вашего объекта запроса содержатся в $ menu_categories и, по крайней мере, имеют свойства -> id -> parent_id & -> title (измените ваши потребности)

$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;
0 голосов
/ 06 августа 2009

Я думаю, что это выводит правильную структуру 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)');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...