【问题标题】:Creating a recursive category tree function创建递归类别树函数
【发布时间】:2012-09-05 16:17:44
【问题描述】:

我有一个包含一堆类别的数据库,其中一些是子类:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Home Improvement
            [slug] => Home-Improvement
            [parent] => 
            [user_id] => 1
            [order] => 1
        )

    [1] => Array
        (
            [id] => 2
            [name] => Asbestos Abatement & Removal
            [slug] => Asbestos-Abatement-Removal
            [parent] => 1
            [user_id] => 1
            [order] => 8
        )

    [2] => Array
        (
            [id] => 3
            [name] => Asphalt & Asphalt Products
            [slug] => Asphalt-Asphalt-Products
            [parent] => 1
            [user_id] => 1
            [order] => 9
        )

    [3] => Array
        (
            [id] => 4
            [name] => Bathroom
            [slug] => Bathroom
            [parent] => 1
            [user_id] => 1
            [order] => 10
        )

    [4] => Array
        (
            [id] => 5
            [name] => Kitchen Cabinets
            [slug] => Kitchen-Cabinets
            [parent] => 1
            [user_id] => 1
            [order] => 11
        )

    [5] => Array
        (
            [id] => 6
            [name] => Ceilings
            [slug] => Ceilings
            [parent] => 1
            [user_id] => 1
            [order] => 12
        )

    [6] => Array
        (
            [id] => 7
            [name] => Cleaning
            [slug] => Cleaning
            [parent] => 1
            [user_id] => 1
            [order] => 13
        )

    [7] => Array
        (
            [id] => 8
            [name] => Closet Organizers & Accessories
            [slug] => Closet-Organizers-Accessories
            [parent] => 1
            [user_id] => 1
            [order] => 14
        )

    [8] => Array
        (
            [id] => 9
            [name] => Concrete
            [slug] => Concrete
            [parent] => 1
            [user_id] => 1
            [order] => 15
        )

    [9] => Array
        (
            [id] => 10
            [name] => Contractors & Service Providers
            [slug] => Contractors-Service-Providers
            [parent] => 1
            [user_id] => 1
            [order] => 16
        )

我想要输出的是这样的:

<ul>
    <li>Parent
        <ul>
            <li>Child</li>
        </ul>
    </li>
    <li>Parent with no Children</li>
</ul>

我正在尝试在 PHP 中构建递归树脚本,但我被卡住了。这是我到目前为止所拥有的。我被困在 else: 和 endif; 之间该怎么做。在 foreach 中。 (我使用这种语法只是为了方便阅读。)有什么建议吗?

echo $this->categories->makeTree(0, $this->db->get('categories')->result_array());

public static function makeTree($parent, $array)
{
  if (!is_array($array)) return '';

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];
        else:

        endif;
    endif;

    $output .= '</li>';
  endforeach;

  $output .= '</ul>';
  return $output;
}

编辑 1

虽然我在 foreach 循环中有一个数据库调用,但我能够让它工作,这可能不是最好的主意:

public function makeTree($parent, $array)
{
  if (!is_array($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $subcategories = ci()->db->get_where('categories', array('parent' => $value['id']));

            if ($subcategories->num_rows() > 0):
                $output .= $this->makeTree($value['id'], $subcategories->result_array());
            endif;
        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';
  return $output;
}

编辑 2

这是我的最终解决方案,重用数组而不是进行数据库查询:

public function makeTree($parent, $array)
{
  if (!is_array($array) OR empty($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $matches = array();

            foreach($array as $subkey => $subvalue):
                if ($subvalue['parent'] == $value['id']):
                    $matches[$subkey] = $subvalue;
                endif;
            endforeach;

            $output .= $this->makeTree($value['id'], $matches);

        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';

  return $output;
}

【问题讨论】:

  • 目前正在穿越2层。我们可以遍历到 n 级吗?

标签: php tree categories


【解决方案1】:

虽然这似乎已回答,但请查看 here。使用显示的函数,您只需一次迭代即可将平面数据转换为嵌套数据。然后从该嵌套数据创建一个 ul-list 非常容易。例如:

function nested2ul($data) {
  $result = array();

  if (sizeof($data) > 0) {
    $result[] = '<ul>';
    foreach ($data as $entry) {
      $result[] = sprintf(
        '<li>%s %s</li>',
        $entry['name'],
        nested2ul($entry['children'])
      );
    }
    $result[] = '</ul>';
  }

  return implode($result);
}

echo nested2ul(array(flat2nested( $yourFlatData ));

这种方法的好处是您不必为了找到子元素而一次又一次地重复输入数据。

【讨论】:

  • 我喜欢这样,但我在 makeRecursive 函数中的return $m[$r][0]; 处不断收到“未定义的偏移量:0”。该函数需要像array(array('id' =&gt; 5273, 'parent' =&gt; 0)) 这样的数据,而我的数组是Array([0] =&gt; Array([id] =&gt; 1, [parent] =&gt; 0))。关于如何解决此问题的任何建议?
  • @dallen 您发布的两个 sn-ps 实际上是相同的。我想问题是你的根父值是一个空字符串。而辅助函数使用0(参见$r 参数)。一个空字符串作为数组键有点问题,所以如果你可以在你的输入数据中改变它,我认为其余的应该可以工作。
【解决方案2】:

这是我的最终解决方案,重用数组而不是执行数据库查询。如果您确实有更好的解决方案,请发布!

public function makeTree($parent, $array)
{
  if (!is_array($array) OR empty($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $matches = array();

            foreach($array as $subkey => $subvalue):
                if ($subvalue['parent'] == $value['id']):
                    $matches[$subkey] = $subvalue;
                endif;
            endforeach;

            $output .= $this->makeTree($value['id'], $matches);

        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';

  return $output;
}

【讨论】:

    【解决方案3】:

    我经常使用这样的东西,请注意

    第一段代码正在使用已弃用的 mysql_*

    第二个你应该有一个名为level的数据库字段,如果为NULL它是主类别,如果它有一个数字,它是该数字作为id的类别的子类别

    function getFamilies($level = 0) {
        $level++;
        $sql = "SELECT id from families WHERE level IS NULL";
        if (mysql_num_rows($result) > 0) {
            echo "<ul>";
                while($row = mysql_fetch_assoc($result)) {
                    echo "<li>".$row['id'];
                        getSubFamilies($level, $row['id']);
                    echo "</li>";
                }
            echo "</ul>";
        }
    }
    
    function getSubFamilies($level, $id) {
        $level++;
        $sqlSubFamilies = "SELECT id  FROM families WHERE level = ".$id."";
        $resultSubFamilies = mysql_query($sqlSubFamilies);
        if (mysql_num_rows($resultSubFamilies) > 0) {
            echo = "<ul>";
                while($rowSubFamilies = mysql_fetch_assoc($resultSubFamilies)) {
                    echo "<li>".$rowSubFamilies['id'];
                        getSubFamilies($level, $rowSubFamilies['id']);
                    echo "</li>";
                }
            echo "</ul>";
        }
    }
    
    getFamilies($level = 0);
    

    【讨论】:

    • 在您的情况下,级别是父级,因此“从父级为空的类别中选择 ID、名称”
    【解决方案4】:

    试试这个:

    $cats = $this->db->get('categories')->result_array();
    
    echo $this->categories->makeTree(0, $cats);
    
    public static function makeTree($parent, $array)
    {
      if (!is_array($array)) return '';
    
      $output = '<ul>';
    
      foreach($array as $key => $value):
        if ($value['parent'] == $parent):
            $output .= '<li>';
    
            if ($value['parent'] == NULL):
                $output .= $value['name'];
            else:
    
            endif;
        endif;
    
        $output .= '</li>';
    
        $output .= $this->categories->makeTree($value['parent'], $cats);
    
      endforeach;
    
      $output .= '</ul>';
      return $output;
    }
    

    【讨论】:

      【解决方案5】:

      我觉得这种使用匿名函数的方法很简单。

      //--------------------------- PRINT NESTED CATEGORIES
      $cats_childs = array();
      
      $q = $db->query("SELECT id, parent, name FROM categories");
      
      while ($r = $db->row($q))
      {
          $cats_childs[$r['parent']][$r['id']] = $r;
      }
      
      $nested2ul = function($data) use (&$nested2ul, &$cats_childs) {
          if (!empty($data)) {
              echo '<ul>';
              foreach ($data as $r) {
                  echo '<li>';
                  echo $r['name'];
                  $flat2ul($cats_childs[$r['id']]);
                  echo '</li>';
              }
              echo '</ul>';
          }
      };
      
      echo $nested2ul($cats_childs[0]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-30
        • 2012-03-18
        • 1970-01-01
        • 1970-01-01
        • 2014-03-20
        相关资源
        最近更新 更多