此类旨在迭代WordPress菜单结构(嵌套数组/对象)以生成完成的菜单。虽然我的数据来源是WordPress,但我觉得这个问题属于SO而不是WP.SO,因为问题更多地存在于PHP中(适用于任何尝试递归的人)。
出于某种原因,我在层次结构中看到了重复的结果。另外,我注意到某些HTML元素没有正确关闭。看起来我已经正确地嵌套了一切,但结果就是你在这里看到的。
为了协助调试,我添加了一些*
来直观地影响标记。也许你们知道我不知道的事情。手指交叉,并提前感谢您的意见!
我的班级
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$output = $this->build_output($this->nested_nav);
$output_formatted = $format->HTML($output);
// echo $output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$output = '**';
$output.= $this->recurse_menu($menu, $output);
return $output;
}
private function recurse_menu( $menu = array(), $output )
{
global $post;
if( !empty($menu) && !empty($output) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$output.= '<li>' . $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= $this->recurse_menu($menu_val->children, $output);
}
// process list items
$output.= '</li>';
}
// process list wrappers
$output.= '</ul>';
}
return $output;
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu');
结果输出
****
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three**
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
后端的WordPress菜单
答案 0 :(得分:0)
如果有人知道原因,我会愿意知道,所以我现在保留选择答案。我的猜测是变量$output
的某种奇怪的命名空间/范围问题。谁知道,我现在有点累。
获得合法结构的解决方法是......
<强>类强>
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
public $output = '';
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$this->build_output($this->nested_nav);
$output_formatted = $format->HTML($this->output);
// echo $this->output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$this->recurse_menu($menu);
}
private function recurse_menu( $menu = array() )
{
global $post;
if( !empty($menu) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$this->output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$this->output.= '<li>';
$this->output.= $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$this->recurse_menu($menu_val->children);
}
// process list items
$this->output.= '</li>';
}
// process list wrappers
$this->output.= '</ul>';
}
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu'); exit;
产生的输出
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
我刚为类创建了一个私有变量,每次我需要将它作为存储位置引用时,我只是附加到它。与以前相同,但不再需要将$output
传递给一些疯狂的方法链。
如果有任何其他想法可以帮助社区,请分享!
答案 1 :(得分:0)
更新 build_output 方法,如下所示:
private function build_output( $menu = array() )
{
$output = '<ul>';
$output = $this->recurse_menu($menu, $output);
$output.= '</ul>';
return $output;
}
更新您的 recurse_menu 方法,如下所示:
private function recurse_menu( $menu = array(), $output = '')
{
global $post;
if( !empty($menu))
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= '<li><a href="#">'.$menu_val->title.'</a><ul class="' . $this->process_classes($classes_ul) . '">'.$this->recurse_menu($menu_val->children).'</ul></li>';
}
else {
$output.= '<li><a href="#">'.$menu_val->title.'</a></li>';
}
}
}
return $output;
}
注意:我已经用更多的子级别进行了测试,它运行正常。