通过API函数,我想定义一个新的Navigation菜单,在当前主题中选择它,然后插入几个Pages作为菜单项。例如,这是在主题激活时完成的。

经过(相当痛苦的)反向工程处理过程,在手动设置“导航”菜单和项目之后,数据库插入和更新,我拼凑了执行以下步骤,其中“ footer-nav”是我正在创建的“导航”菜单的子条目ID:

if (!term_exists('footer-nav', 'nav_menu')) {

    $menu = wp_insert_term('Footer nav', 'nav_menu', array('slug' => 'footer-nav'));

    // Select this menu in the current theme
    update_option('theme_mods_'.get_current_theme(), array("nav_menu_locations" => array("primary" => $menu['term_id'])));

    // Insert new page
    $page = wp_insert_post(array('post_title' => 'Blog',
                                 'post_content' => '',
                                 'post_status' => 'publish',
                                 'post_type' => 'page'));

    // Insert new nav_menu_item
    $nav_item = wp_insert_post(array('post_title' => 'News',
                                     'post_content' => '',
                                     'post_status' => 'publish',
                                     'post_type' => 'nav_menu_item'));


    add_post_meta($nav_item, '_menu_item_type', 'post_type');
    add_post_meta($nav_item, '_menu_item_menu_item_parent', '0');
    add_post_meta($nav_item, '_menu_item_object_id', $page);
    add_post_meta($nav_item, '_menu_item_object', 'page');
    add_post_meta($nav_item, '_menu_item_target', '');
    add_post_meta($nav_item, '_menu_item_classes', 'a:1:{i:0;s:0:"";}');
    add_post_meta($nav_item, '_menu_item_xfn', '');
    add_post_meta($nav_item, '_menu_item_url', '');

    wp_set_object_terms($nav_item, 'footer-nav', 'nav_menu');
}


这似乎可行,但是:


这是一种健壮且优雅的方法吗?
我遗漏了完全显而易见的东西,可以在一行代码中完成所有这一切吗?


#1 楼

我可能会误解您,但为什么不使用wp_create_nav_menu()

例如,当我检测到BP处于活动状态时,这就是创建自定义BuddyPress菜单的方法:

    $menuname = $lblg_themename . ' BuddyPress Menu';
$bpmenulocation = 'lblgbpmenu';
// Does the menu exist already?
$menu_exists = wp_get_nav_menu_object( $menuname );

// If it doesn't exist, let's create it.
if( !$menu_exists){
    $menu_id = wp_create_nav_menu($menuname);

    // Set up default BuddyPress links and add them to the menu.
    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Home'),
        'menu-item-classes' => 'home',
        'menu-item-url' => home_url( '/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Activity'),
        'menu-item-classes' => 'activity',
        'menu-item-url' => home_url( '/activity/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Members'),
        'menu-item-classes' => 'members',
        'menu-item-url' => home_url( '/members/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Groups'),
        'menu-item-classes' => 'groups',
        'menu-item-url' => home_url( '/groups/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Forums'),
        'menu-item-classes' => 'forums',
        'menu-item-url' => home_url( '/forums/' ), 
        'menu-item-status' => 'publish'));

    // Grab the theme locations and assign our newly-created menu
    // to the BuddyPress menu location.
    if( !has_nav_menu( $bpmenulocation ) ){
        $locations = get_theme_mod('nav_menu_locations');
        $locations[$bpmenulocation] = $menu_id;
        set_theme_mod( 'nav_menu_locations', $locations );
    }


评论


我不知道这个功能。是的,我想它将使上面的代码更短。我想我应该超越Codex并深入研究实际代码,因为我发现API函数通常(在这种情况下)太底层了。谢谢!

– julien_c
2012年3月7日14:18

@julien_c如果已解决,请将其标记为允许在您之后的人从您的经验中受益。

–mor7ifer
2012年3月7日15:07

我只想在现实生活中对其进行实际测试,所以我确定它可以满足我的要求。完成后,我会立即将其标记为已解决!

– julien_c
2012年3月7日15:51

如果您看到类似的有用功能不在法典中,则最好添加它们(是维基)= p

– Tom J Nowell♦
2012年3月9日19:51

抱歉,我花了很长时间检查它是否适合我的情况。答案已接受!另外,您正在定义自定义链接菜单项,我在下面添加了一个答案来定义页面链接(例如,它对URL更改更可靠)。

– julien_c
2012年5月15日上午11:06

#2 楼

作为ZaMoose答案的补充,以下是创建“页面类型”菜单项(而不是“自定义”菜单项)的方法:

wp_update_nav_menu_item($menu_id, 0, array('menu-item-title' => 'About',
                                           'menu-item-object' => 'page',
                                           'menu-item-object-id' => get_page_by_path('about')->ID,
                                           'menu-item-type' => 'post_type',
                                           'menu-item-status' => 'publish'));


假设您只知道例如,页面。

#3 楼

我对可接受的答案有一些疑问-并没有弄错,但是我将发布自己的代码,在下面的代码中,由于我有相同的问题,但我想做同样的事情,因此对于某些人来说可能会有更好的结果只需较少的代码即可。

首先,以上代码创建了“ URL”类型的导航项,对某些人来说很好,但我想链接到PAGES,而不是URL,因为这是WordPress的重要功能导航和客户端不可避免地会四处移动,因此我从不使用URL导航项类型。

此外,发布的代码仅处理平面的子代数组。我创建了一个函数,用于递归声明新的导航项,存储它们返回的元数据(主要是在循环中创建后的ID),以及一个用于接受子项的参数。

只需编辑$nav_items_to_add,其余的递归处理。每个数组中有3个必需的键。首先,阵列键是子弹,因此'shop' => array( ... )是您想要的带有子弹shop的页面的内容。 ['title']是在前端标记导航项的方式。 path是WordPress页面层次结构中页面的路径,因此,如果该页面是顶级父级,则它与slug相同;如果shophome的子级,则它将是'path' => 'home/shop'

最后一个可选的数组键是['parent'],您可以在数组中将另一个键声明为当前键的父键。重要的是要注意,这些项是递归添加的,因此在尝试创建子项之前,父项必须存在。这意味着声明应在父项导航到子项之前进行。

    $locations = get_nav_menu_locations();

    if (isset($locations['primary_navigation'])) {
        $menu_id = $locations['primary_navigation'];

        $new_menu_obj = array();

        $nav_items_to_add = array(
                'shop' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    ),
                'shop_l2' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    'parent' => 'shop',
                    ),
                'cart' => array(
                    'title' => 'Cart',
                    'path' => 'shop/cart',
                    'parent' => 'shop',
                    ),
                'checkout' => array(
                    'title' => 'Checkout',
                    'path' => 'shop/checkout',
                    'parent' => 'shop',
                    ),
                'my-account' => array(
                    'title' => 'My Account',
                    'path' => 'shop/my-account',
                    'parent' => 'shop',
                    ),
                'lost-password' => array(
                    'title' => 'Lost Password',
                    'path' => 'shop/my-account/lost-password',
                    'parent' => 'my-account',
                    ),
                'edit-address' => array(
                    'title' => 'Edit My Address',
                    'path' => 'shop/my-account/edit-address',
                    'parent' => 'my-account',
                    ),
            );

    foreach ( $nav_items_to_add as $slug => $nav_item ) {
        $new_menu_obj[$slug] = array();
        if ( array_key_exists( 'parent', $nav_item ) )
            $new_menu_obj[$slug]['parent'] = $nav_item['parent'];
        $new_menu_obj[$slug]['id'] = wp_update_nav_menu_item($menu_id, 0,  array(
                'menu-item-title' => $nav_item['title'],
                'menu-item-object' => 'page',
                'menu-item-parent-id' => $new_menu_obj[ $nav_item['parent'] ]['id'],
                'menu-item-object-id' => get_page_by_path( $nav_item['path'] )->ID,
                'menu-item-type' => 'post_type',
                'menu-item-status' => 'publish')
        );
    }

    }


评论


那是一个非常聪明的解决方案。感谢您添加。正是我所需要的。

– Juergen
20年6月2日,9:47

#4 楼

以编程方式添加菜单项。您可以挂钩到wp_nav_menu_items过滤器。在主题functions.php中的代码下面放置以在主菜单中添加登录/注销菜单项。 “ Primary”是已注册菜单的名称/ ID。

/**
 * Add login logout menu item in the main menu.
 * ===========================================
 */

add_filter( 'wp_nav_menu_items', 'lunchbox_add_loginout_link', 10, 2 );
function lunchbox_add_loginout_link( $items, $args ) {
    /**
     * If menu primary menu is set & user is logged in.
     */
    if ( is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. wp_logout_url() .'">Log Out</a></li>';
    }
    /**
     * Else display login menu item.
     */
    elseif ( !is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. site_url('wp-login.php') .'">Log In</a></li>';
    }
    return $items;
}