如果菜单项在wp_get_NAV_Menu_Items挂接中有子项,则搜索

时间:2020-06-01 作者:pixelngrain

我有条件地显示菜单项。一切正常,但如果不返回子项,则希望删除父项。

例如,如果我有一个名为More 并且它有多个子项(主要是一个级别)。现在,如果我基于用户角色隐藏子项,并且对于某些角色没有可用的子项,那么我想删除More 菜单项,因为它没有子项。

我正在尝试以下代码,但自$item 是一个对象,array_search 行不通。那么,如果菜单项没有子级,我如何检查子级父级并删除该菜单项呢?

array_search( $item[ \'ID\' ], array_column( $item, \'menu_item_parent\' ) )
下面是根据用户角色隐藏菜单项的工作代码。

public static function exclude_menu_items( $items, $menu, $args ) {

    if ( current_user_can( \'administrator\' ) ) {
        return $items;
    }

    foreach ( $items as $key => $item ) {

        if ( $page = get_post( $item->object_id ) ) {
            if ( $page->post_type == \'page\' ) {
                $template  = get_post_meta( $page->ID, \'_wp_page_template\', TRUE );
                $post_type = self::get_cpt_for_template( $template );

                if ( $post_type && ( ! current_user_can( \'cp_access_\' . $post_type ) || ! ( new self() )->is_current_user_granted_for_module( $post_type ) ) ) {
                    unset( $items[ $key ] );
                }
            }
        }
    }

    return $items;
}

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

如果要使用wp_get_nav_menu_items 钩住,然后尝试下面的函数,该函数应在exclude_menu_items 功能:

// Example when NOT using a class: (you already defined the exclude_menu_items function)
add_filter( \'wp_get_nav_menu_items\', \'exclude_menu_items\', 10, 3 );
add_filter( \'wp_get_nav_menu_items\', \'exclude_menu_items2\' );

function exclude_menu_items2( $items ) {
    if ( current_user_can( \'administrator\' ) ) {
        return $items;
    }

    $mores   = [];
    $parents = [];
    foreach ( $items as $key => $item ) {
        if ( \'#\' === $item->url && \'More\' === $item->title ) {
            $mores[] = $item->ID;
        }

        if ( ! in_array( $item->menu_item_parent, $parents ) ) {
            $parents[] = $item->menu_item_parent;
        }
    }

    $mores = array_diff( $mores, $parents );
    foreach ( $items as $i => $item ) {
        if ( in_array( $item->ID, $mores ) ) {
            unset( $items[ $i ] );
        }
    }

    return $items;
}
只需确保运行适当的验证,以便菜单项不会被弄乱,例如在菜单管理屏幕上。

这两种功能也可以组合使用:

function exclude_menu_items( $items, $menu, $args ) {
    if ( current_user_can( \'administrator\' ) ) {
        return $items;
    }

    $mores   = [];
    $parents = [];
    foreach ( $items as $key => $item ) {
        if ( $page = get_post( $item->object_id ) ) {
            // ... your code here.
        }

        if ( ! empty( $items[ $key ] ) ) {
            if ( \'#\' === $item->url && \'More\' === $item->title ) {
                $mores[] = $item->ID;
            }

            if ( ! in_array( $item->menu_item_parent, $parents ) ) {
                $parents[] = $item->menu_item_parent;
            }
        }
    }

    $mores = array_diff( $mores, $parents );
    foreach ( $items as $i => $item ) {
        if ( in_array( $item->ID, $mores ) ) {
            unset( $items[ $i ] );
        }
    }

    return $items;
}
事实上;什么时候wp_nav_menu() 称为—使用wp_nav_menu_objects hook, 删除没有子项的“更多”项目更简单:

add_filter( \'wp_nav_menu_objects\', function ( $items ) {
    if ( is_admin() ) { // sample validation..
        return $items;
    }

    return array_filter( $items, function ( $item ) {
        return ! ( \'#\' === $item->url && \'More\' === $item->title &&
            ! in_array( \'menu-item-has-children\', $item->classes )
        );
    } );
} );

SO网友:dimitrisv

在这里,您可以找到一种更深入的方法来处理wp\\u get\\u nav\\u菜单项的限制

它使用SQL确定子项,但提供了更大的灵活性,以便完全控制您实际想要做的事情:

   //this query produces all you need to have for the children at any depth. It is explained on the readme and will spare you the add on walkers.   
                            $query = "SELECT e.id, e.post_title, CASE WHEN c.meta_value=\'custom\' THEN ( d.meta_value) ELSE concat (\'/\', e.post_name ,\'/\') END as linkurl, b.post_id 
                                                FROM wp_postmeta a FORCE INDEX (post_id)
                                                JOIN wp_postmeta b FORCE INDEX (post_id) ON a.post_id=b.post_id
                                                JOIN wp_postmeta c FORCE INDEX (post_id) ON c.post_id=b.post_id
                                                JOIN wp_postmeta d FORCE INDEX (post_id) ON d.post_id=b.post_id
                                                JOIN wp_posts e ON e.id=b.meta_value
                                                WHERE d.meta_key=\'_menu_item_url\' AND c.meta_key=\'_menu_item_object\' AND b.meta_key=\'_menu_item_object_id\' 
                                                AND a.meta_key=\'_menu_item_menu_item_parent\' AND a.meta_value=\'" . $submenu->ID . "\'";

                            $resultsData = $wpdb->get_results($query);

                            foreach ($resultsData as $childrenData) {

                                $menu_html_s .=   \'<!-- Lets print each of the children  -->\';
                                $menu_html_s .=   \'<div class="menu-sub menu-sub-accordion menu-active-bg">\';
                                $menu_html_s .=   \'<div class="menu-item">\';
                                $menu_html_s .=   \'<a class="menu-link" href="\' . $childrenData->linkurl . \'">\';
                                $menu_html_s .=   \'<span class="menu-bullet">\';
                                $menu_html_s .=   \'<span class="bullet bullet-dot"></span>\';
                                $menu_html_s .=   \'</span>\';
                                $menu_html_s .=   \'<span class="menu-title">\' . $childrenData->post_title . \'</span>\';
                                $menu_html_s .=   \'</a>\';
                                $menu_html_s .=   \'</div>\';
                                $menu_html_s .=   \'</div>\';
更多详细信息请参见:

https://github.com/exonianp/wp-bootstrap5-accordeon-vertical-menu

相关推荐

Making sub-menus exclusive

我真的不知道该怎么解释我在这里找的东西,我在这里找得太露骨了。在我的网站上,我有一个附带菜单,其中包含一系列子类别,每个子类别中都有一些项目。我想知道当我打开另一个子类别时,是否有办法关闭所有其他打开的子类别,例如:1. Animals ----A. Cats ----B. Dogs 2. People ----A. Samantha ----B. Daniel 当我按下“动物”时,我希望“人”关闭,反之亦