Wordpress - 我怎么知道菜单项是否有孩子?

kik*_*ito 24 php wordpress

我正在开发一个带有嵌套子菜单的wordpress主题.我需要让没有孩子的元素与有孩子的元素在视觉上不同.现在我有这个菜单,但可能会改变:

A
  a1
  a2
B
  b1
  b2
C
Run Code Online (Sandbox Code Playgroud)

如你所见,A和B有孩子.C没有 - 我需要它在CSS级别上有所不同.

理想情况下,我想has-children在A和B中有一个类,但在C中没有.

到目前为止,我已经设法创建了一个"Menu Walker"PHP类,我可以实例化并传递给wp_nav_menu.它的构造函数如下所示:

class My_Walker_Nav_Menu extends Walker_Nav_Menu {
  function start_el(&$output, $item, $depth, $args) {
    ...
    if(??? $item has children???) {
      // I know what to do here
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

那么,我该如何判断是否$item有孩子,或者是叶子?

编辑:这个问题由Wordpress论坛中名为"keesiemeijer"的人回答.我要离开这个赏金过期以防他想要收回它.否则,我会将自己的答案标记为有效.

jan*_*anw 32

functions.php其添加到它将向父母添加"下拉"类

性能的新方式

function menu_set_dropdown( $sorted_menu_items, $args ) {
    $last_top = 0;
    foreach ( $sorted_menu_items as $key => $obj ) {
        // it is a top lv item?
        if ( 0 == $obj->menu_item_parent ) {
            // set the key of the parent
            $last_top = $key;
        } else {
            $sorted_menu_items[$last_top]->classes['dropdown'] = 'dropdown';
        }
    }
    return $sorted_menu_items;
}
add_filter( 'wp_nav_menu_objects', 'menu_set_dropdown', 10, 2 );
Run Code Online (Sandbox Code Playgroud)

旧:数据库密集

add_filter( 'nav_menu_css_class', 'check_for_submenu', 10, 2);
function check_for_submenu($classes, $item) {
    global $wpdb;
    $has_children = $wpdb->get_var("SELECT COUNT(meta_id) FROM wp_postmeta WHERE meta_key='_menu_item_menu_item_parent' AND meta_value='".$item->ID."'");
    if ($has_children > 0) array_push($classes,'dropdown'); // add the class dropdown to the current list
    return $classes;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此方法会为每个菜单项添加另一个数据库查询,如果您有很多菜单项,可能会降低您的网站速度! (2认同)
  • 它在wp 3.6中没有效果?还有什么要添加或删除的东西?即时通讯使用wp_nav_menu() (2认同)

sta*_*406 17

你用这种方式很简单:

说明:我用"walker"创建菜单:

$walker = new Nav_Walker;
wp_nav_menu(array(
        'container'=>'nav',
        'container_class'=>'menu',
        'menu_class'=>'list-unstyled list-inline',
        'walker'=>$walker
    ));
Run Code Online (Sandbox Code Playgroud)

班沃克:

class Nav_Walker extends Walker_Nav_Menu
{ 
      public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
    {
        if($args->walker->has_children)
        {
            //code...
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)

我们有对象'walker',你可以通过var_dump($ args)来查看更多内容.我正在使用我的项目!

  • 欢迎来到SO,starrynight,谢谢你的第一个答案.一些建议,以获得更好的答案得分:包括一个解释_Why_您的代码将解决OP的问题. (3认同)

Jor*_*ran 9

似乎问题终于得到了解决.截至当前写作4.0的最新Wordpress测试版更新了Walker_Nav_Menu类并添加了$has_children属性.

/**
 * Whether the current element has children or not.
 *
 * To be used in start_el().
 *
 * @since 4.0.0
 * @access protected
 * @var bool
 */
protected $has_children;
Run Code Online (Sandbox Code Playgroud)

所以,我们不再需要破解function display_element(...)了.


Eug*_*lov 6

class My_Walker_Nav_Menu extends Walker_Nav_Menu {
  function start_el(&$output, $item, $depth, $args) {
    ...
    if($args['has_children']) {
      // I know what to do here
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • `if ($args->walker->has_children)` (11认同)
  • 恐怕这行不通。有两个原因 - 首先, `$args` 是一个 `stdObject`,而不是一个 `array` - 所以语法是 `$args->has_children`。其次,“$args”没有“has_children”属性(我使用“var_dump($args)”进行了检查)。它或“$item”似乎都没有这样的属性。 (2认同)

kik*_*ito 6

我在WordPress论坛上问过,keesiemeijer把我指向了另一篇文章,其中他们做了以下内容:

start_el他们修改了display_element,而不是修改,添加以下两行(这里是第37-38行):

//display this element (THESE ARE NOT THE LINES)
if ( is_array( $args[0] ) )
  $args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );

// THESE TWO ARE THE LINES:               
if( ! empty( $children_elements[$element->$id_field] ) )
  array_push($element->classes,'parent');
Run Code Online (Sandbox Code Playgroud)

我将前两行留作空间参考,并作为对此帖中其他答案的评论.似乎wordpress正在"尝试"设置'has_children'属性$args,但它要么做错了,要么以我不理解的方式做错.在任何情况下,该has_children参数永远不会传递给start_el(参见此处 $ args的示例var_dump )

这可能是我得到的Wordpress版本(3.2.1)上的一个错误,可能已在最新版本中修复.

在任何情况下,我在Wordpress论坛中得到的答案是帮助我解决它的答案,所以我认为这已经解决了.我会等到赏金到期,以防keesiemeijer想把答案放在这里.