【发布时间】:2011-02-04 22:45:41
【问题描述】:
我在数据库中有一个表,其中包含指向我网站页面的各种路径。每条路径仅列出一次。我目前有一系列非常长且复杂的查询和 PHP 来提取所有这些并将数据重写为无序列表(为我的网站创建菜单)。似乎有一种相对简单的循环方法可以更有效地工作,但我似乎无法得到任何工作。我发现大量 PHP 脚本可以从文件树创建 UL 列表,但它们要么不起作用,要么无法处理我的查询结果固有的非递归性质(有些需要我的路径的多维数组,其中会很好,除了我创建这些的麻烦)。我确实找到了一个非常接近的脚本,但是它通过将子列表放在<li> 部分之外来错误地格式化<ul> 部分(我将在下面解释)
这是一个示例:
DB 在结果数组中返回以下内容:
about/contact/
about/contact/form/
about/history/
about/staff/
about/staff/bobjones/
about/staff/sallymae/
products/
products/gifts/
products/widgets/
我想创建以下输出:
<ul>
<li>about/
<ul>
<li>about/contact/
<ul>
<li>about/contact/form/</li>
</ul>
</li>
<li>about/history/</li>
<li>about/staff/
<ul>
<li>about/staff/bobjones/</li>
<li>about/staff/sallymae/</li>
</ul>
</li>
</ul>
</li>
<li>products/
<ul>
<li>products/gifts/</li>
<li>products/widgets/</li>
</ul>
</li>
</ul>
所以我非常接近在此处找到的脚本:http://www.daniweb.com/forums/thread285916.html,但我遇到了问题。事实证明,我发现的脚本创建了格式不正确的 UL 列表。在正确的情况下,子列表包含在父元素的<li> 中。在此脚本中,父 <li> 关闭,然后插入 <ul> 块。整个脚本在跟上关卡等方面实际上相当优雅,但我无法完全理解它以弄清楚如何修复它。我在这里有一个函数的全部内容:
function generateMainMenu()
{
global $db;
$MenuListOutput = '';
$PathsArray = array();
$sql = "SELECT PageUrlName FROM `table`";
$result = mysql_query($sql, $db) or die('MySQL error: ' . mysql_error());
while ($PageDataArray = mysql_fetch_array($result))
{
$PathsArray[] = rtrim($PageDataArray['PageUrlName'],"/"); //this function does not like paths to end in a slash, so remove trailing slash before saving to array
}
sort($PathsArray);// These need to be sorted.
$MenuListOutput .= '<ul id="nav">'."\n";//get things started off right
$directories=array ();
$topmark=0;
$submenu=0;
foreach ($PathsArray as $value) {
// break up each path into it's constituent directories
$limb=explode("/",$value);
for($i=0;$i<count($limb);$i++) {
if ($i+1==count($limb)){
// It's the 'Leaf' of the tree, so it needs a link
if ($topmark>$i){
// the previous path had more directories, therefore more Unordered Lists.
$MenuListOutput .= str_repeat("</ul>",$topmark-$i); // Close off the Unordered Lists
$MenuListOutput .= "\n";// For neatness
}
$MenuListOutput .= '<li><a href="/'.$value.'">'.$limb[$i]."</a></li>\n";// Print the Leaf link
$topmark=$i;// Establish the number of directories in this path
}else{
// It's a directory
if($directories[$i]!=$limb[$i]){
// If the directory is the same as the previous path we are not interested.
if ($topmark>$i){// the previous path had more directories, therefore more Unordered Lists.
$MenuListOutput .= str_repeat("</ul>",$topmark-$i);// Close off the Unordered Lists
$MenuListOutput .= "\n";// For neatness
}
// (next line replaced to avoid duplicate listing of each parent)
//$MenuListOutput .= "<li>".$limb[$i]."</li>\n<ul>\n";
$MenuListOutput .= "<ul>\n";
$submenu++;// Increment the dropdown.
$directories[$i]=$limb[$i];// Mark it so that if the next path's directory in a similar position is the same, it won't be processed.
}
}
}
}
$MenuListOutput .= str_repeat("</ul>",$topmark+1);// Close off the Unordered Lists
return $MenuListOutput."\n\n\n";
}
它会返回如下内容:
<ul id="nav">
<li><a href="/about">about</a></li>
<ul>
<li><a href="/about/history">history</a></li>
<li><a href="/about/job-opportunities">job-opportunities</a></li>
<li><a href="/about/mission">mission</a></li>
<li><a href="/about/privacy-policy">privacy-policy</a></li>
</ul>
<li><a href="/giftcards">giftcards</a></li>
<li><a href="/locations">locations</a></li>
<ul>
<li><a href="/locations/main-office">main-office</a></li>
<li><a href="/locations/branch-office">branch-office</a></li>
</ul>
<li><a href="/packages">packages</a></li>
</ul>
任何人都知道我需要在哪里添加一些额外的逻辑以及如何实现这一点?关于更好的方法的其他想法?似乎这是一个如此普遍的问题,以至于会有一种简单/标准的方法来处理这样的事情。也许如果我能弄清楚如何从我的路径创建一个多维数组,那么可以迭代这些以使其工作?
编辑:更复杂:-(
我尝试了 casablanca 的回应,效果非常好……但后来我意识到,现在我有后续行动让事情变得更加困难。为了显示页面的“名称”,我还需要在数组中包含该信息,因此路径可能更适合作为数组键和值中的名称。任何关于改变的想法:
$paths = array(
"about/contact/ " => "Contact Us",
"about/contact/form/ " => "Contact Form",
"about/history/ " => "Our History",
"about/staff/ " => "Our Staff",
"about/staff/bobjones/ " => "Bob",
"about/staff/sallymae/ " => "Sally",
"products/ " => "All Products",
"products/gifts/ " => "Gift Ideas!",
"products/widgets/ " => "Widgets"
);
然后在buildUL 函数中使用类似这一行的内容:
echo '<a href="'.$prefix.$key.'/">'.$paths[$prefix.$key].'</a>';
【问题讨论】:
-
必须使用递归的经典案例。也许你想用谷歌搜索那个词。
-
解决原始问题的最简单方法是删除
</li>标签。它们在 HTML 中是可选的,删除它们将导致元素自动按正确的层次结构排序。