使用<ul> <li> </li> </ul>进行递归函数

时间:2013-06-23 10:21:34

标签: php mysql recursion

目前我正在以文本格式显示带有递归函数的数据,如..

Food    
    Fruit
        Red
            Apple
        Yellow
            Banana
    Meat
        Beef
        Pork

我正在使用以下代码来显示此文本

function display_children($parent, $level) { 
    $result = mysql_query('SELECT * FROM category '.
    'WHERE parant_id="'.$parent.'";'); 

    while ($row = mysql_fetch_array($result)) { 
        echo str_repeat('    ',$level).$row['name']."\n"; 
        display_children($row['id'], $level+1); 
    } 
} 

display_children(0,0);

但现在我想在<ul> <li>菜单中显示上述文字,如

<ul>
    <li>Food
        <ul>
            <li>Fruit
                <ul>
                    <li>Red
                        <ul>
                            <li>Apple</li>
                        </ul>
                    </li>
                    <li>Yellow
                        <ul>
                            <li>Banana</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>Meat
                <ul>
                    <li>Beef</li>
                    <li>Pork</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

所有数据都以下列格式存储在表格中

+----+-----------+--------+
| id | parant_id |  name  |
+----+-----------+--------+
|  1 |         0 | Food   |
|  2 |         1 | Fruit  |
|  3 |         1 | Meat   |
|  4 |         2 | Red    |
|  5 |         2 | Yellow |
|  6 |         4 | Apple  |
|  7 |         5 | Banana |
|  8 |         3 | Beef   |
|  9 |         3 | Pork   |
+----+-----------+--------+

请帮我以<ul> <li>格式

显示整个数据

由于

2 个答案:

答案 0 :(得分:2)

// pass a full row to the function instead of only the id
// also, with this solution you don't need the level, but I kept it there, you can use it for styling, etc.
function display_with_children($parentRow, $level) { 
    echo '<li>'.$parentRow['name']; 
    // if your id column is integer, you don't need the quotation mark
    $result = mysql_query('SELECT * FROM category WHERE parant_id='.$parentRow['id'].';');
    if (mysql_num_rows($result) != 0) {
        echo '<ul>';
        // use the fetch_assoc to get an associative array
        while ($row = mysql_fetch_assoc($result)) { 
            display_with_children($row, $level+1); 
        } 
        echo '</ul>';
    }
    echo '</li>';
} 

并像

一样使用它
$rootRow = ....;
echo '<ul>';
display_with_children($rootRow, 0);
ehco '</ul>;

编辑:请注意,此解决方案相当理论化,因为它存在性能问题(请参阅注释)。如果没有太多的类别,最好从数据库中一起获取它们,并从内存中递归处理它们,除了检索每个类别的子项的方式之外,这类似。如果你有大量的嵌套类别或标签,并且你需要经常处理它们的部分树,你可以考虑使用nested set model

答案 1 :(得分:2)

我更喜欢只执行一个mysql查询,然后尝试避免递归(因为内存使用)。输出是一个数组,其中所有项目都是有序的=&gt;子元素始终跟随其父元素。非常有用的是children其中是所有直接孩子的列表。只有一个限制:由于$digits=2;,每个父母的子女的最大数量为99。您可以将其更改为$digits=3;并将加注次数计算为999;)

数据库记录:

id  parent  name
1     0     Food
2     1     Fruit
3     2     Red
4     3     Apple
5     2     Yellow
6     5     Banana
7     1     Meat
8     7     Beef
9     7     Pork

<强> CODE:

$query = "SELECT * FROM `menu` ORDER BY `parent`";
$result = mysqli_query($dbc, $query);
$data = array();
while ($row = mysqli_fetch_assoc($result)) {
    $data[$row['id']] = $row;
}


/******************* ARRAY LIST GENERATOR *******************/
$digits = 2;
$menu = array();
$added = 1;
while ($added) {
    $added = 0;
    foreach ($data as $k => &$v) {
        if (!isset($v['key'])) {
            if (!$v['parent']) {
                $key = sprintf("%0{$digits}d", ++$added);
                $menu[$key] = $v;
                $v['key'] = $key;
                $menu[$key]['parentKey'] = 0;
                $menu[$key]['level'] = 1;
            } else {
                if (isset($data[$v['parent']]['key']) && isset($menu[$data[$v['parent']]['key']])) {
                    if (isset($menu[$data[$v['parent']]['key']]['children'])) {
                        $key = $data[$v['parent']]['key'] . sprintf("%0{$digits}d", count($menu[$data[$v['parent']]['key']]['children']) + 1);
                        $menu[$data[$v['parent']]['key']]['children'][] = $key;
                    } else {
                        $key = $data[$v['parent']]['key'] . sprintf("%0{$digits}d", 1);
                        $menu[$data[$v['parent']]['key']]['children'][] = $key;
                    }
                    $menu[$key] = $v;
                    $menu[$key]['parentKey'] = $data[$v['parent']]['key'];
                    $menu[$key]['level'] = $menu[$menu[$key]['parentKey']]['level'] + 1;
                    $v['key'] = $key;
                    $added++;
                }
            }
        }
    }
}

ksort($menu, SORT_STRING);

/******************* UL LI GENERATOR *******************/
$li = array();
$ul = array();
$levelLL = 0;
echo "<ul>\n";
$ul[1] = 1;
foreach ($menu as $k => &$v) {
    if ($v['level'] < $levelLL) {
        for ($i = $levelLL; $i > $v['level'] - 1; $i--) {
            if (isset($li[$i])) {
                echo "</li>\n";
                unset($li[$i]);
            }
            if (isset($ul[$i]) && $i > $v['level']) {
                echo "</ul>\n";
                unset($ul[$i]);
            }
        }
    } elseif ($v['level'] == $levelLL) {
        echo "</li>\n";
    }
    echo "<li>\n";
    $li[$v['level']] = 1;
    echo $v['name'] . "\n";
    if (isset($v['children'])) {
        echo "<ul>\n";
        $ul[$v['level'] + 1] = 1;
    }
    $levelLL = $v['level'];
}
if (0 < $levelLL) {
    for ($i = $levelLL; $i > -1; $i--) {
        if (isset($li[$i])) {
            echo "</li>\n";
            unset($li[$i]);
        }
        if (isset($ul[$i]) && $i > 0) {
            echo "</ul>\n";
            unset($ul[$i]);
        }
    }
}

<强>输出:

<ul>
    <li>
        Food
        <ul>
            <li>
                Fruit
                <ul>
                    <li>
                        Red
                        <ul>
                            <li>
                                Apple
                            </li>
                        </ul>
                    </li>
                    <li>
                        Yellow
                        <ul>
                            <li>
                                Banana
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>
                Meat
                <ul>
                    <li>
                        Beef
                    </li>
                    <li>
                        Pork
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>