我认为这不是一个简单的方法,但这是我的家庭任务,所以请耐心等待。
我在Mysql 'menu'
中有一个表,其结构如下:
id - number
parent_id - number (0 for root)
title - string
link - string
parent_id与某一行的ID相关联,在这种情况下product1
与products
。
example :
1 | 0 | about | about.html
2 | 0 | products | products.html
3 | 2 | product1 | product1.html
4 | 2 | product2 | product2.html
5 | 2 | product3 | product3.html
我的目标是制作一组看起来像这样的ul
:
<ul>
<li><a href="about.html"> about </a></li>
<li><a href="products.html"> products </a>
<ul>
<li> <a href="product1.html"> product 1 </a></li>
<li> <a href="product1.html"> product 1 </a></li>
...
</ul>
</li>
...
</ul>
到目前为止,我只做了一个ul
:
<?php
function getAll() {
DBconnect();
$result = mysql_query("SELECT * FROM `menu`");
$listitems = array();
while ($li = mysql_fetch_array($result)) {
$listitems[] = $li;
}
return $listitems;
}
?>
<ul>
<?php
include_once 'functions.php';
$listitems = getAll();
foreach ($listitems as $listitem) {
?>
<li><a href="<?php print $listitem['link']; ?>"><?php print $listitem['title']; ?></a></li>
<?php } ?>
</ul>
这是问题的开始,我无法弄清楚如何制作第二个函数或如何调整它以使“子菜单”行成为ul
中的ul
答案 0 :(得分:2)
如果表中没有大量元素,则很容易解决这个问题。正如Syed Qarib用户所说,你可以检查当前项目是否有一些孩子。
关键是使用parent_id使html的绘制递归。
这是您需要的代码:
<?php
function getElementsByParentId($parent_id) {
DBconnect();
$query = sprintf("SELECT * FROM `menu` WHERE parent_id=%s",
mysql_real_escape_string($parent_id));
$result = mysql_query($query);
<!-- Alternative using concat
$result = mysql_query("SELECT * FROM `menu` WHERE parent_id=".$parent_id);
-->
$listitems = array();
while ($li = mysql_fetch_array($result)) {
$listitems[] = $li;
}
return $listitems;
}
function paintChildrens($parent_id) {
$listitems = getElementsByParentId($parent_id);
if (count($listitems) > 0) {
?>
<ul>
<?php
foreach($listitems as $listitem) {
?>
<li><a href="<?php print $listitem['link']; ?>"><?php print $listitem['title']; ?></a></li>
<?php
paintChildrens($listitem['id']);
}
?>
</ul>
<?php
}
}
include_once 'functions.php';
paintChildrens(null) ?>
我不是PHP开发人员,因此有可能此代码存在一些错误,例如空值检查。
答案 1 :(得分:1)
有两种方法可以解决这个问题:
1.递归地从数据库中选择数据(上面提出了这种方法)。这在加载和数据库查询的数量方面是不好的。但是这种方法在代码方面更简单。
2.从表中选择所有记录,并在PHP上形成一个查询树。下面我举例说明如何操作(PHP版本&gt; = 5.4)
<?php
function itemsCmd($a, $b)
{
return strnatcmp($a['path'], $b['path']);
}
function getAll()
{
// fetch all from DB
$itemsRaw = [
['id' => 1, 'parent_id' => 0, 'title' => 'about', 'link' => 'about.html'],
['id' => 2, 'parent_id' => 0, 'title' => 'products', 'link' => 'products.html'],
['id' => 3, 'parent_id' => 2, 'title' => 'product1', 'link' => 'product1.html'],
['id' => 4, 'parent_id' => 2, 'title' => 'product2', 'link' => 'product2.html'],
['id' => 5, 'parent_id' => 3, 'title' => 'product11', 'link' => 'product11.html'],
['id' => 6, 'parent_id' => 4, 'title' => 'product21', 'link' => 'product21.html'],
['id' => 7, 'parent_id' => 4, 'title' => 'product22', 'link' => 'product22.html'],
];
// get path for each item (like /1/2/4) and item level from 0 to N
$items = [];
foreach ($itemsRaw as $key => $item) {
$item['path'] = [$item['id']];
$item['level'] = 0;
$parentId = $item['parent_id'];
while ($parentId) {
foreach ($itemsRaw as $row) {
if ($row['id'] == $parentId) {
$newParentId = $row['parent_id'];
$item['path'][] = $row['id'];
break;
}
}
$parentId = $newParentId;
$item['level']++;
}
$item['path'] = implode('/', array_reverse($item['path']));
$items[] = $item;
}
// order items by path
usort($items, 'itemsCmd');
return $items;
}
?>
<ul>
<? $currentLevel = 0; ?>
<? foreach (getAll() as $index => $item) :?>
<?php if ($currentLevel < $item['level']) : ?>
<ul>
<li>
<?=$item['title']?>
<?php elseif ($currentLevel > $item['level']) : ?>
<? for($i = 0; $i < $currentLevel; $i++) : ?>
</li>
</ul>
<? endfor ?>
<li>
<?=$item['title']?>
<?php else : ?>
<? if ($index) :?>
</li>
<? endif ?>
<li>
<?=$item['title']?>
<?php endif ?>
<? $currentLevel = $item['level']?>
<? endforeach ?>
<? for($i = 0; $i < $currentLevel; $i++) : ?>
</li>
</ul>
<? endfor ?>
答案 2 :(得分:1)
尝试:
function menu ( $p )
{
$hdr = 0;
foreach ($li in $listitems)
{
if ( $li['parent_id'] == $p )
{
if ( !$hdr ) { $hdr++; echo "<UL>";
echo "<LI>...";
menu( $li['id'] );
}
}
if ( $hdr ) echo "</UL>";
}
使用:
menu( 0 );
代替现有的html生成代码。
这应该适用于任意数量的子菜单级别。