【问题标题】:How to create a hierarchical list from data如何从数据创建分层列表
【发布时间】:2018-03-26 19:20:11
【问题描述】:

使用 PHP,我需要创建一个三层深度的导航栏。我有这样的数据:

我需要这样组织:

Napkins --Colored Napkins ----American Tradition --White Beverage Napkins ----American Digital ----American Tradition ----American Hi-Speed --White Luncheon Napkins ----American Digital ----American Tradition ----American Hi-Speed --White Dinner Napkins ...(etc)... Plates --Eco-Plates ----American Tradition --Plastic Trays ...(etc)...

只是使用了一个相对简单的<ul> 结构与<li><a>。显然需要一个循环来遍历数据行。而且我知道我需要做很多“测试”来查看“当前”类别/子类别/方法是否与循环的上一次迭代中的匹配。

但是当只有 一个 打印方法时,我无法让 <ul> and <li> 标记在正确的位置关闭并且不显示打印方法层对于给定的类别/子类别。或者当有no打印方法时(有时可以是null,比如塑料器皿)。我该如何设置?

编辑

我目前的代码,几乎可以运行,但是非常笨重($items 是数据库中的数据):

function addMethodMenuItem($result, $short_cat_name, $short_subcat_name, $short_method_name, $this_method_name)
{
    $result .= "<li>";
    $result .= "<a";
    $result .= " href=\"product.php?category={$short_cat_name}&subcategory={$short_subcat_name}&printMethod={$short_method_name}\"";
    $result .= " target=\"_self\"";
    $result .= " title=\"{$this_method_name}\">";
    $result .= $this_method_name;
    $result .= "</a>";
    $result .= "</li>";
    return $result;
}

function addSubMenuItem($item, $previous_cat_name, $previous_subcat_name, $result, $newCat)
{
    $this_cat_name = $item["category_name"];
    $this_subcat_name = $item["subcategory_name"];
    $this_method_name = $item["method_name"];
    $short_cat_name = $item["category_short"];
    $short_subcat_name = $item["subcategory_short"];
    $short_method_name = $item["method_short"];

    if ($this_subcat_name != $previous_subcat_name || $this_cat_name != $previous_cat_name) { // We have to create a new "subcategory" menu item
        if ($previous_subcat_name != null && !$newCat) { // if this isn't the first subcategory menu item of the category.
            $result .= "</ul></li>";
        }
        $result .= "<li>";
        $result .= "<a class=\"ajxsub\"";
        $result .= " href=\"#\">";
        $result .= $this_subcat_name;
        $result .= "</a>";
        $result .= "<ul>";
    }

    $result = addMethodMenuItem($result, $short_cat_name, $short_subcat_name, $short_method_name, $this_method_name);
    return $result;
}

function printMenu(array $items, $previous_cat_name, $result)
{
    // $result .= "<ul>";
    $previous_subcat_name = null;
    foreach ($items as $item) {
        $newCat = false;
        $this_cat_name = $item["category_name"];
        $this_subcat_name = $item["subcategory_name"];
        if ($this_cat_name != $previous_cat_name) {
            if ($previous_cat_name != null) { // if this isn't the very first top-level menu item.
                $result .= "</ul></li>";
                $result .= "</ul></li>";
                $newCat = true;
            }
            $result .= "<li>";
            $result .= "<a class=\"ajxsub\"";
            $result .= " href=\"#\">";
            $result .= $this_cat_name;
            $result .= "</a>";
            $result .= "<ul>";
        }
        $result = addSubMenuItem($item, $previous_cat_name, $previous_subcat_name, $result, $newCat);
        $previous_subcat_name = $this_subcat_name;
        $previous_cat_name = $this_cat_name;
    }
    $result .= "</ul></li>";
    // $result .= "</ul>";

    return $result;
}

【问题讨论】:

标签: php html-lists navbar hierarchy


【解决方案1】:

试一试 - 假设您已经对数据进行了排序(否则先对其进行排序):

$flds = ['category_name', 'subcategory_name', 'method_name'];
$lval = ['it will never be this'];
$result = "";
$start = true;
foreach ($items as $item) {
    if ($start) {
        $result .= "<ul>";
        $first = $start = false;
    } else $first = true;
    foreach ($flds as $k=>$val) {
        if ($item[$val] != $lval[$k]) {
            $result .= genhtml($k, $item[$val], $first);
            $first = false;
            $lval[$k] = $item[$val];
            $lval[$k+1] = '';   // Don't care if this goes over the max
        }
    }
}
if (!$start) $result .= "</ul></li></ul></li></ul>\n";
echo $result;

function genhtml($level, $value, $first) {
    switch ($level) {
        case 0:
            $close = $first ? "</ul></li></ul></li>" : "";
            return "{$close}<li><a href=\"#\" class=\"level0\">{$value}</a><ul>\n";
        case 1:
            $close = $first ? "</ul></li>" : "";
            return "  {$close}<li><a href=\"#\" class=\"level1\">{$value}</a><ul>\n";
        case 2:
            return "    <li><a href=\"#\" class=\"level2\">{$value}</a></li>\n";
        default:
            throw new Exception("I don't know how to do '{$level}'");
    }
}

上面的代码(带有你的一些数据)产生:

<ul><li><a href="#" class="level0">Napkins</a><ul>
  <li><a href="#" class="level1">Colored Napkins</a><ul>
    <li><a href="#" class="level2">American Tradition</a></li>
  </ul></li><li><a href="#" class="level1">White Beverage Napkins</a><ul>
    <li><a href="#" class="level2">American Digital</a></li>
    <li><a href="#" class="level2">American Tradition</a></li>
    <li><a href="#" class="level2">American Hi Speed</a></li>
  </ul></li><li><a href="#" class="level1">White Luncheon Napkins</a><ul>
    <li><a href="#" class="level2">American Digital</a></li>
    <li><a href="#" class="level2">American Tradition</a></li>
    <li><a href="#" class="level2">American Hi Speed</a></li>
  </ul></li><li><a href="#" class="level1">White Dinner Napkins</a><ul>
    <li><a href="#" class="level2">American Digital</a></li>
    <li><a href="#" class="level2">American Tradition</a></li>
    <li><a href="#" class="level2">American Hi Speed</a></li>
</ul></li></ul></li><li><a href="#" class="level0">Plates</a><ul>
  <li><a href="#" class="level1">Eco Plates</a><ul>
    <li><a href="#" class="level2">American Tradition</a></li>
</ul></li></ul></li></ul>

(不漂亮,但我认为它是正确的)。

还会忽略重复记录(可能不是您想要的?)。如果您需要记录中的其他数据来生成 html,请将 $item 也传递给 genhtml。

【讨论】:

  • 非常好!我喜欢它如何跟踪每个级别的先前值以进行后续比较;我没有想到这一点。绝对比我拥有东西的笨拙方式更好。我实际上已经让我的代码工作(现在),对我的原始帖子进行了一些细微的改动,但它相当脆弱,所以我很可能很快就会改变为你更优雅的解决方案。非常感谢@wordragon!
猜你喜欢
  • 2023-03-09
  • 2021-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 2022-11-28
相关资源
最近更新 更多