如何在 PHP 中从连接字符串构建树?

MrS*_*rSo 1 php mysql recursion

我尝试从存储在 mysql 数据库中的串联字符串中的层次结构在 PHP 中创建一个树列表

这是我的桌子:

表格截图

我想重现这样的事情:

<ul>
  <li>
    <ul>
      <li></li>
      <li>
          <ul>
              <li></li>
              <li></li>
           </ul>
      </li>
      <li></li>
    </ul>
  </li>
  <li></li>
  <li></li>
</ul>
Run Code Online (Sandbox Code Playgroud)

我知道我必须使用我无法做到的递归函数......

也许有人可以帮助我

Peb*_*bbl 5

没有注释的代码

请参阅下面的用法和数据集部分,了解您需要传递什么以及如何使用这些函数:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)


带有注释和解释的代码

将项目转换为树结构的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

将树结构转换为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;
  }
}
Run Code Online (Sandbox Code Playgroud)

数据集:

/// 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'),
);
Run Code Online (Sandbox Code Playgroud)

用法:

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

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

echo $html;
Run Code Online (Sandbox Code Playgroud)


为了代码高尔夫的利益;)

以下内容可以代替我的items_to_tree功能——但不建议这样做。

$a = array();
foreach($items as $i){
 eval('$a["'.str_replace('.','"]["',$i['hierarchy']).'"]=array("#item"=>$i);');
}
Run Code Online (Sandbox Code Playgroud)