如何在PHP中从类别字符串创建嵌套类别列表

时间:2013-09-09 19:59:07

标签: php mysql

我有一个MySQL表“产品”,其中有一个名为“category”的列。在此字段中,您可以将每个产品的类别层次结构视为字符串。 E.g:

female / dresses / long
female / dresses / short
female / shoes  
male / shoes / sneakers / skate
...

我选择了所有不同的类别:

$result = $mysqli->query("SELECT DISTINCT category FROM products ORDER BY category");

现在,我希望能够将这些类别打印为嵌套的HTML列表,如

    • 礼服
      • 运动鞋
        • 溜冰鞋

非常感谢任何建议。谢谢!

编辑:我从几个csv文件中获取数据,因此无需转换类别的解决方案就会很棒!

2 个答案:

答案 0 :(得分:1)

使用类别作为节点的键来构建树。例如:

$categoryLines = array(
    "female / dresses / long",
    "female / dresses / short",
    "female / shoes",
    "male / shoes / sneakers / skate"
);

function buildCategoryTree($categoryLines, $separator) {
    $catTree = array();
    foreach ($categoryLines as $catLine) {
       $path = explode($separator, $catLine);
       $node = & $catTree;
       foreach ($path as $cat) {
           $cat = trim($cat);
           if (!isset($node[$cat])) {
               $node[$cat] = array();
           }
           $node = & $node[$cat];
       }
    }
    return $catTree;
}

function displayCategoryTree($categoryTree, $indent = '') {
    foreach ($categoryTree as $node => $children) {
        echo $indent . $node . "\n";
        displayCategoryTree($children, $indent . '|- ');
    }
}

$categoryTree = buildCategoryTree($categoryLines, '/');

现在,var_export($categoryTree)将输出:

array (
  'female' => array (
    'dresses' => array (
      'long' => array (),
      'short' => array (),
    ),
    'shoes' => array (),
  ),
  'male' => array (
    'shoes' => array (
      'sneakers' => array (
        'skate' => array (),
      ),
    ),
  ),
)

displayCategoryTree($categoryTree)将输出:

female
|- dresses
|- |- long
|- |- short
|- shoes
male
|- shoes
|- |- sneakers
|- |- |- skate

**编辑**

获取树的HTML表示:

function displayHtmlCategoryTree($categoryTree, $id = null, $pathSeparator = '/', $parents = '') {
    if (empty($categoryTree)) return '';

    $str = '<ul' . (!empty($id) ? ' id="'.$id.'"' : '') . '>';
    foreach ($categoryTree as $node => $children) {
        $currentPath = $parents . (empty($parents) ? '' : $pathSeparator) . $node;
        $str .= '<li title="' . $currentPath . '">' . $node . 
                displayHtmlCategoryTree($children, null, $pathSeparator, $currentPath) . 
                '</li>';
    }
    $str .= '</ul>';
    return $str;
}

echo displayHtmlCategoryTree($categoryTree, "test", ' / ');

并输出:

<ul id="test"><li title="female">female<ul><li title="female / dresses">dresses<ul><li title="female / dresses / long">long</li><li title="female / dresses / short">short</li></ul></li><li title="female / shoes">shoes</li></ul></li><li title="male">male<ul><li title="male / shoes">shoes<ul><li title="male / shoes / sneakers">sneakers<ul><li title="male / shoes / sneakers / skate">skate</li></ul></li></ul></li></ul></li></ul>

答案 1 :(得分:0)

正如其他人在评论中提到的那样,您最好使用nested tree sets进行此类分类,但是因为您要求您不想更改类别系统和IF的方案,并且仅限于您不关心你的运行时超载,你可以使用我写的代码。

用于填充类别数组:

<?php
  $rows = array(
    "female/dresses/long",
    "female/dresses/short",
    "female/dresses/short/1",
    "female/dresses/short/2",
    "female/dresses/short/2/1",
    "female/shoes",
    "male/shoes/sneakers/skate"
  );

  $categories = array();

  function populate()
  {
    global $rows;
    global $categories;

    foreach($rows as $row)
    {
      $category_array = explode(" / ", $row);

      $categories = place($categories, $category_array);
    }
  }

  function place($categories, $category, $counter = 0)
  {
    if($counter < count($category))
    {
      if(!isset($categories[$category[$counter]]))
      {
        $categories[$category[$counter]] = array();
      }
      else if($counter == count($category) - 1)
      {
        $categories[$category[$counter]][] = $category[$counter];
      }

      // Recurse
      $categories[$category[$counter]] = place($categories[$category[$counter]], $category, $counter + 1);
    }

    return $categories;
  }

  // Populate categories
  populate();
?>

您可以使用fetch foreach循环替换$rows上的while

用于显示类别:

<?php
  function display($items)
  {
    foreach($items as $k => $v)
    {
      echo "<li>" . $k;

      if(is_array($v))
      {
        echo "<ul>";

        display($v);

        echo "</ul>";
      }

      echo "</li>";
    }
  }
?>

<!DOCTYPE HTML>

<html>

<head>
  <title>Categories</title>
</head>

<body>
  <ul>
  <?php
    // Display categories
    display($categories);
  ?>
  </ul>
</body>

</html>

当前示范:

female
    dresses
        long
        short
            1
            2
                1
    shoes

male
    shoes
        sneakers
            skate