我正在尝试从源数组生成一个多级HTML列表,格式如下:
/**
* id = unique id
* parent_id = "id" that this item is directly nested under
* text = the output string
*/
$list = array(
array(
'id' => 1,
'parent_id' => 0,
'text' => 'Level 1',
), array(
'id' => 2,
'parent_id' => 0,
'text' => 'Level 2',
), array(
'id' => 3,
'parent_id' => 2,
'text' => 'Level 2.1',
), array(
'id' => 4,
'parent_id' => 2,
'text' => 'Level 2.2',
), array(
'id' => 5,
'parent_id' => 4,
'text' => 'Level 2.2.1',
), array(
'id' => 6,
'parent_id' => 0,
'text' => 'Level 3',
)
);
Run Code Online (Sandbox Code Playgroud)
目标是嵌套<ul>无限深度.上面数组的预期输出是这样的:
如果只有数组项有一个被调用的键child或者包含实际子数组的东西,那么很容易通过这些来递归并使用如下函数获得所需的输出:
function makeList($list)
{
echo '<ul>';
foreach ($list as $item)
{
echo '<li>'.$item['text'];
if (isset($item['child']))
{
makeList($item['child']);
}
echo '</li>';
}
echo '</ul>';
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,对我来说并非如此 - 源数组的格式无法更改.因此,很久以前我写了这个非常讨厌的函数来实现它,它只能工作三个级别(代码是逐字粘贴原始注释).我知道这是一个漫长无聊的读物,请耐心等待:
function makeArray($links)
{
// Output
$nav = array();
foreach ($links as $k => $v)
{
// If no parent_id is present, we can assume it is a top-level link
if (empty($v['parent_id']))
{
$id = isset($v['id']) ? $v['id'] : $k;
$nav[$id] = $v;
// Remove from original array
unset($links[$k]);
}
}
// Loop through the remaining links again,
// we can assume they all have a parent_id
foreach ($links as $k => $v)
{
// Link's parent_id is in the top level array, so this is a level-2 link
// We already looped through every item so we know they are all accounted for
if (isset($nav[$v['parent_id']]))
{
$id = isset($v['id']) ? $v['id'] : $k;
// Add it to the top level links as a child
$nav[$v['parent_id']]['child'][$id] = $v;
// Set a marker so we know which ones to loop through to add the third level
$nav2[$id] = $v;
// Remove it from the array
unset($links[$k]);
}
}
// Last iteration for the third level
// All other links have been removed from the original array at this point
foreach ($links as $k => $v)
{
$id = isset($v['id']) ? $v['id'] : $k;
// Link's parent_id is in the second level array, so this is a level-3 link
// Orphans will be ignored
if (isset($nav2[$v['parent_id']]))
{
// This part is crazy, just go with it
$nav3 = $nav2[$v['parent_id']]['parent_id'];
$nav[$nav3]['child'][$v['parent_id']]['child'][] = $v;
}
}
return $nav;
}
Run Code Online (Sandbox Code Playgroud)
这使得数组像:
array(
'text' => 'Level 1'
'child' => array(
array(
'text' => 'Level 1.2'
'child' => array(
array(
'text' => 'Level 1.2.1'
'child' => array(
// etc.
),
array(
'text' => 'Level 1.2.2'
'child' => array(
// etc.
),
)
)
)
)
);
Run Code Online (Sandbox Code Playgroud)
用法:
$nav = makeArray($links);
makeList($nav);
Run Code Online (Sandbox Code Playgroud)
我花了很多时间试图解决这个问题,我在这里给出的原始代码仍然是我能够生成的最佳解决方案.
如果没有那个可怕的功能(限制在3的深度),并且具有无限多个级别,我怎样才能实现这一点?有更优雅的解决方案吗?
打印:
function printListRecursive(&$list,$parent=0){
$foundSome = false;
for( $i=0,$c=count($list);$i<$c;$i++ ){
if( $list[$i]['parent_id']==$parent ){
if( $foundSome==false ){
echo '<ul>';
$foundSome = true;
}
echo '<li>'.$list[$i]['text'].'</li>';
printListRecursive($list,$list[$i]['id']);
}
}
if( $foundSome ){
echo '</ul>';
}
}
printListRecursive($list);
Run Code Online (Sandbox Code Playgroud)
创建多维数组:
function makeListRecursive(&$list,$parent=0){
$result = array();
for( $i=0,$c=count($list);$i<$c;$i++ ){
if( $list[$i]['parent_id']==$parent ){
$list[$i]['childs'] = makeListRecursive($list,$list[$i]['id']);
$result[] = $list[$i];
}
}
return $result;
}
$result = array();
$result = makeListRecursive($list);
echo '<pre>';
var_dump($result);
echo '</pre>';
Run Code Online (Sandbox Code Playgroud)