简体   繁体   English

如何用PHP中的串联字符串构建树?

[英]How to build a tree from a concatenated string in PHP?

I try to make a tree list in PHP from a hierarchy stored in a concatenated string in my mysql database 我尝试从存储在我的mysql数据库的串联字符串中的层次结构中的PHP中创建树列表

This my table : 这是我的桌子:

表格截图

and I'd like to reproduce something like this : 我想重现这样的东西:

<ul>
  <li>
    <ul>
      <li></li>
      <li>
          <ul>
              <li></li>
              <li></li>
           </ul>
      </li>
      <li></li>
    </ul>
  </li>
  <li></li>
  <li></li>
</ul>

I know I have to use a recursive function I don't reach to do... 我知道我必须使用递归函数,但我无法做到...

Maybe someone could help me 也许有人可以帮我

code without comments 没有注释的代码

see the usage and dataset section below to see what you need to pass and how to use these functions: 请参阅下面的用法和数据集部分,以了解需要传递的内容以及如何使用这些功能:

function items_to_tree( $items ){
  $array = array();
  foreach( $items as $item ) {
    $parts = explode('.', $item['hierarchy']);
    $last = array_pop( $parts );
    $cursor = &$array;
    foreach ( $parts as $part ) {
      if ( !is_array($cursor[$part]) ) {
        $cursor[$part] = array();
      }
      $cursor = &$cursor[$part];
    }
    $cursor[$last]['#item'] = $item;
  }
  return $array;
}

function tree_to_ul( $tree ){
  $html = $children = '';
  foreach( $tree as $key => $item ){
    if ( substr($key,0,1) == '#' ) continue;
    $children .= tree_to_ul( $item );
  }
  if ( isset($tree['#item']) ) {
    $html .= '<li>' . PHP_EOL;
    $html .= '<em>' . $tree['#item']['menu_text'] . '</em>' . PHP_EOL;
    $html .= ( $children ? '<ul>' . $children . '</ul>' . PHP_EOL : '' );
    $html .= '</li>' . PHP_EOL;
    return $html;
  }
  else {
    return $children;
  }
}


code with comments and explanation 带有注释和解释的代码

The code to convert your items to a tree structure: 将项目转换为树形结构的代码:

function items_to_tree( $items ){
  $array = array();
  foreach( $items as $item ) {
    /// split each hierarchy string into it's dot separated parts
    $parts = explode('.', $item['hierarchy']);
    /// pop off the last item of the array, we'll use this for assignment later
    $last = array_pop( $parts );
    /// create a reference to our position in the array we wish to fill out
    $cursor = &$array;
    /// step each hierarchy part and travel down the array structure, 
    /// just like you would if you typed an array path manually. 
    /// i.e. $array[$part][$part][...] and so on
    foreach ( $parts as $part ) {
      /// if at this point in the array, we don't have an array, make one.
      if ( !is_array($cursor[$part]) ) {
        $cursor[$part] = array();
      }
      /// ready for the next step, shift our reference to point to the next
      /// $part in the array chain. e.g. if $cursor pointed to `$array[$part]`
      /// before, after the next line of code the $cursor will point 
      /// to `$array[$oldpart][$part]`
      $cursor = &$cursor[$part];
    }
    /// we popped the last item off the $parts array so we could easily
    /// assign our final value to where the $cursor ends up pointing to.
    /// starting with a hierarchy of '00001.00002.00003' would mean at this
    /// point $cursor points to $array['00001']['00002'] and $last = '00003';
    /// so finally we get $array['00001']['00002']['00003']['#item'] = $item;
    $cursor[$last]['#item'] = $item;
    /// use '#item' to keep our item's information separate from it's children.
  }
  /// return our built up array.
  return $array;
}

The code to convert the tree structure to a UL: 将树结构转换为UL的代码:

function tree_to_ul( $tree ){
  /// start with nothing
  $html = $children = '';
  /// step each item found in the current level of $tree
  foreach( $tree as $key => $item ){
    /// if the item's key starts with a # skip, these contain
    /// our item's information and should not be treated as children
    if ( substr($key,0,1) == '#' ) continue;
    /// recurse this function so that we do the same for any child @ any level.
    $children .= tree_to_ul( $item );
  }
  /// if at this level a #item has been set, use this item information to
  /// add a title to our level. You could change this to add whatever info
  /// from your original database item that you'd like.
  if ( isset($tree['#item']) ) {
    $html .= '<li>' . PHP_EOL;
    $html .= '<em>' . $tree['#item']['menu_text'] . '</em>' . PHP_EOL;
    $html .= ( $children ? '<ul>' . $children . '</ul>' . PHP_EOL : '' );
    $html .= '</li>' . PHP_EOL;
    return $html;
  }
  /// if there wasn't an item, just return the traversed children.
  else {
    return $children;
  }
}

dataset: 数据集:

/// I simplified your dataset to an array, this could easily be generated
/// from a database query. You could also convert my code so that you
/// don't have to pre-generate an array, and instead could process after
/// each fetch from the database.

$items = array(
  array('hierarchy' => '00001',             'menu_text' => 'One'),
  array('hierarchy' => '00002',             'menu_text' => 'Two'),
  array('hierarchy' => '00002.00001',       'menu_text' => 'Three'),
  array('hierarchy' => '00002.00002',       'menu_text' => 'Four'),
  array('hierarchy' => '00002.00003',       'menu_text' => 'Five'),
  array('hierarchy' => '00002.00004',       'menu_text' => 'Six'),
  array('hierarchy' => '00003',             'menu_text' => 'Seven'),
  array('hierarchy' => '00003.00001',       'menu_text' => 'Eight'),
  array('hierarchy' => '00003.00001.00001', 'menu_text' => 'Nine'),
  array('hierarchy' => '00003.00001.00002', 'menu_text' => 'Ten'),
  array('hierarchy' => '00003.00001.00003', 'menu_text' => 'Eleven'),
  array('hierarchy' => '00003.00002',       'menu_text' => 'Twelve'),
);

usage: 用法:

/// Simple usage :) if a little complex explanation

$tree = items_to_tree( $items );
$html = tree_to_ul( $tree );

echo $html;


in the interests of codegolf ;) 为了代码高尔夫的利益;)

The following could replace my items_to_tree function -- however it isn't advised. 以下内容可以代替我的items_to_tree函数-但不建议这样做。

$a = array();
foreach($items as $i){
 eval('$a["'.str_replace('.','"]["',$i['hierarchy']).'"]=array("#item"=>$i);');
}
    $refs = new stdClass();
    //Assuming $data is the result array of your query to fetch the data.
    foreach($data as $result)
    {
        $name = $result['hierarchy'];
        $parent = substr($result['hierarchy'],0,strrpos($result['hierarchy'],'.'));
        $thisref = &$refs->{$name};
        foreach($result as $k => $v)
        {
            $thisref->{$k} = $v;
        }
        if ($parent == '') {
            $tree->{$name} = &$thisref;
        } else {
            $refs->{$parent}->children->{$name} = &$thisref;
        }
    }

This will give you a nice object with every node's child in the property children. 这将为您提供一个不错的对象,其子节点属性中的每个节点的子节点都可以。

function drawUL($level){
    echo '<ul>';
    foreach($level as $li){
        echo '<li>'.$li->label;
        if(isset($li->children))drawUl($li->children);
        echo '</li>';
    }
    echo '</ul>';
}
drawUl($tree);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM