将路径数组转换为UL列表 [英] Convert array of paths into UL list

查看:96
本文介绍了将路径数组转换为UL列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在数据库中有一个表,该表包含指向我的网站页面的各种路径.每个路径仅列出一次.我目前有一系列冗长而费解的查询,而PHP会将所有这些查询和数据重写为一个无序列表(为我的网站创建菜单).似乎有一种相对简单的循环方法可以更有效地工作,但我似乎无法使任何工作.我发现有大量的PHP脚本可从文件树创建UL列表,但它们要么不起作用,要么无法处理查询结果固有的非递归性质(有些需要路径的多维数组,会很好,除非我在创建这些文件时遇到麻烦).我确实找到了一个工作得非常接近的脚本,但是通过将子列表放在<li>部分之外(我将在下面解释)

I have a table in a database that contains a variety of paths to pages of my website. Each path is listed only one time. I currently have a very long and convoluted series of queries and PHP to pull all these and rewrite the data into an unordered list (to create a menu for my website). It seems that there is probably a relatively simple looping approach that would work MUCH more efficiently, but I cannot seem to get anything working. I have found TONS of PHP scripts that create UL lists from file trees, but all of them either don't work or can't handle the inherently not recursive nature of my query results (some require multi-dimensional arrays of my paths, which would be fine except for my trouble with creating those). I did find a script that works pretty close, but it formats the <ul> portion incorrectly by placing sub-lists outside of the <li> section (I will explain below)

以下是示例:

DB在结果数组中返回以下内容:

DB returns the following in results array:

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>块.实际上,总体脚本在与级别等方面保持一致的方式相当优雅,但是我无法将其束缚在脑海中,以至于无法找到解决方法.我把整个东西放在这里的函数中:

So I got very close with a script found here: http://www.daniweb.com/forums/thread285916.html but I have run into a problem. It turns out that the script that I found creates improperly formatted UL lists. In a CORRECT situation, a sub-list is contained within the <li> of the parent element. In this scripting, the parent <li> is closed and then a <ul> block is inserted. The overall script is actually fairly elegant in the way that it keeps up with the levels and such, but I cannot wrap my head around it enough to figure out how to fix it. I have the whole thing in a function here:

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>

任何人都知道我需要在哪里添加一些其他逻辑,以及如何才能做到这一点?还有其他更好的方法吗?似乎这是一个普遍的问题,将有一种简单/标准的方法来处理类似的事情.也许如果我能弄清楚如何从路径中创建多维数组,那么可以迭代这些数组以完成这项工作?

Anyone have an idea of where I need to add in some additional logic and how I can accomplish this? Other ideas on a better way to do this? It seems like this is such a common issue that there would be a simple/standard method of handling something like this. Maybe if I could figure out how to create a multi-dimensional array from my paths then those could be iterated to make this work?

更复杂:-(

我尝试了卡萨布兰卡的回应,但效果很好……只是我后来意识到现在我有后续行动使事情变得更加困难.为了显示页面的名称",我还需要在数组中包含该信息,因此该路径可能更好地用作数组键和值中的名称.关于这种变化的任何想法:

I tried casablanca's response and it worked perfectly...except I then realized that now I have a follow-up to make things more difficult. In order to display the "name" of the page, I need to also have that info in the array, thus the path probably works better as the array key and the name in the value. Any thoughts on changing like this:

$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函数中使用以下代码:

and then using something like this line within the buildUL function:

echo '<a href="'.$prefix.$key.'/">'.$paths[$prefix.$key].'</a>';

推荐答案

已更改为满足更新的问题.

Changed to cater for updated question.

我正在使用__title的数组索引来保存页面标题.只要树中永远没有名为__title的目录,就可以了.您可以随意将此哨兵值更改为所需的任何内容.

I'm using an array index of __title to hold the page title. As long as you never have a directory in your tree called __title this should be fine. You're free to change this sentinel value to anything you wish however.

我也对其进行了更改,以便列表构建函数返回一个字符串,以便您可以存储该值以供以后在页面中使用. (您当然可以执行echo build_list(build_tree($paths))直接输出列表.

I have also changed it so the list building function returns a string, so that you can store the value for use later in your page. (You can of course just do echo build_list(build_tree($paths)) to output the list directly.

<?php

$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'
);

function build_tree($path_list) {
    $path_tree = array();
    foreach ($path_list as $path => $title) {
        $list = explode('/', trim($path, '/'));
        $last_dir = &$path_tree;
        foreach ($list as $dir) {
            $last_dir =& $last_dir[$dir];
        }
        $last_dir['__title'] = $title;
    }
    return $path_tree;
}

function build_list($tree, $prefix = '') {
    $ul = '';
    foreach ($tree as $key => $value) {
        $li = '';
        if (is_array($value)) {
            if (array_key_exists('__title', $value)) {
                $li .= "$prefix$key/ <a href=\"/$prefix$key/\">${value['__title']}</a>";
            } else {
                $li .= "$prefix$key/";
            }
            $li .= build_list($value, "$prefix$key/");
            $ul .= strlen($li) ? "<li>$li</li>" : '';
        }
    }
    return strlen($ul) ? "<ul>$ul</ul>" : '';
}

$tree = build_tree($paths);
$list = build_list($tree);
echo $list;

?>

这篇关于将路径数组转换为UL列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆